Skip to content

Commit 75ed1dc

Browse files
committed
Move simple field access to accessor functions
This helps encapsulation by ensuring that no outside users can mutate these fields. Reducing the amount of logic that needs to be reasoned about.
1 parent f2683b7 commit 75ed1dc

File tree

3 files changed

+86
-48
lines changed

3 files changed

+86
-48
lines changed

quinn-proto/src/connection/mod.rs

Lines changed: 44 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,7 @@ impl Connection {
519519
// always spill into the next datagram.
520520
let pn = self.packet_number_filter.peek(&self.spaces[SpaceId::Data]);
521521
let frame_space_1rtt = buf
522-
.segment_size
522+
.segment_size()
523523
.saturating_sub(self.predict_1rtt_overhead(Some(pn)));
524524

525525
// Is there data or a close message to send in this space?
@@ -558,11 +558,11 @@ impl Connection {
558558
// We are NOT coalescing (the default is we are, so this was turned off in an
559559
// earlier iteration) OR there is not enough space for another *packet* in this
560560
// datagram (buf_capacity - buf_end == unused space in datagram).
561-
if !coalesce || buf.buf_capacity - buf_end < MIN_PACKET_SPACE + tag_len {
561+
if !coalesce || buf.datagram_max_offset() - buf_end < MIN_PACKET_SPACE + tag_len {
562562
// We need to send 1 more datagram and extend the buffer for that.
563563

564564
// Is 1 more datagram allowed?
565-
if buf.num_datagrams >= buf.max_datagrams {
565+
if buf.num_datagrams() >= buf.max_datagrams() {
566566
// No more datagrams allowed
567567
break;
568568
}
@@ -573,10 +573,9 @@ impl Connection {
573573
// for starting another datagram. If there is any anti-amplification
574574
// budget left, we always allow a full MTU to be sent
575575
// (see https://github.com/quinn-rs/quinn/issues/1082)
576-
if self
577-
.path
578-
.anti_amplification_blocked((buf.segment_size * buf.num_datagrams) as u64 + 1)
579-
{
576+
if self.path.anti_amplification_blocked(
577+
(buf.segment_size() * buf.num_datagrams()) as u64 + 1,
578+
) {
580579
trace!("blocked by anti-amplification");
581580
break;
582581
}
@@ -586,13 +585,13 @@ impl Connection {
586585
if ack_eliciting && self.spaces[space_id].loss_probes == 0 {
587586
// Assume the current packet will get padded to fill the segment
588587
let untracked_bytes = if let Some(builder) = &builder_storage {
589-
buf.buf_capacity - builder.partial_encode.start
588+
buf.datagram_max_offset() - builder.partial_encode.start
590589
} else {
591590
0
592591
} as u64;
593-
debug_assert!(untracked_bytes <= buf.segment_size as u64);
592+
debug_assert!(untracked_bytes <= buf.segment_size() as u64);
594593

595-
let bytes_to_send = buf.segment_size as u64 + untracked_bytes;
594+
let bytes_to_send = buf.segment_size() as u64 + untracked_bytes;
596595
if self.path.in_flight.bytes + bytes_to_send >= self.path.congestion.window() {
597596
space_idx += 1;
598597
congestion_blocked = true;
@@ -626,7 +625,7 @@ impl Connection {
626625
builder.pad_to(MIN_INITIAL_SIZE);
627626
}
628627

629-
if buf.num_datagrams > 1 {
628+
if buf.num_datagrams() > 1 {
630629
// If too many padding bytes would be required to continue the GSO batch
631630
// after this packet, end the GSO batch here. Ensures that fixed-size frames
632631
// with heterogeneous sizes (e.g. application datagrams) won't inadvertently
@@ -641,42 +640,45 @@ impl Connection {
641640
// `buf_capacity` by less than `segment_size`.
642641
const MAX_PADDING: usize = 16;
643642
let packet_len_unpadded = cmp::max(builder.min_size, buf.len())
644-
- buf.datagram_start
643+
- buf.datagram_start_offset()
645644
+ builder.tag_len;
646-
if packet_len_unpadded + MAX_PADDING < buf.segment_size
647-
|| buf.datagram_start + buf.segment_size > buf.buf_capacity
645+
if packet_len_unpadded + MAX_PADDING < buf.segment_size()
646+
|| buf.datagram_start_offset() + buf.segment_size()
647+
> buf.datagram_max_offset()
648648
{
649649
trace!(
650650
"GSO truncated by demand for {} padding bytes or loss probe",
651-
buf.segment_size - packet_len_unpadded
651+
buf.segment_size() - packet_len_unpadded
652652
);
653653
builder_storage = Some(builder);
654654
break;
655655
}
656656

657657
// Pad the current datagram to GSO segment size so it can be included in the
658658
// GSO batch.
659-
builder.pad_to(buf.segment_size as u16);
659+
builder.pad_to(buf.segment_size() as u16);
660660
}
661661

662662
builder.finish_and_track(now, self, sent_frames.take(), buf.buf);
663663

664-
if buf.num_datagrams == 1 && space_id == SpaceId::Data {
665-
// Now that we know the size of the first datagram, check whether
666-
// the data we planned to send will fit in the next segment. If
667-
// not, bails out and leave it for the next GSO batch. We can't
668-
// easily compute the right segment size before the original call to
669-
// `space_can_send`, because at that time we haven't determined
670-
// whether we're going to coalesce with the first datagram or
671-
// potentially pad it to `MIN_INITIAL_SIZE`.
672-
664+
if buf.num_datagrams() == 1 {
673665
buf.clip_datagram_size();
674-
675-
let frame_space_1rtt = buf
676-
.segment_size
677-
.saturating_sub(self.predict_1rtt_overhead(Some(pn)));
678-
if self.space_can_send(space_id, frame_space_1rtt).is_empty() {
679-
break;
666+
if space_id == SpaceId::Data {
667+
// Now that we know the size of the first datagram, check
668+
// whether the data we planned to send will fit in the next
669+
// segment. If not, bails out and leave it for the next GSO
670+
// batch. We can't easily compute the right segment size before
671+
// the original call to `space_can_send`, because at that time
672+
// we haven't determined whether we're going to coalesce with
673+
// the first datagram or potentially pad it to
674+
// `MIN_INITIAL_SIZE`.
675+
676+
let frame_space_1rtt = buf
677+
.segment_size()
678+
.saturating_sub(self.predict_1rtt_overhead(Some(pn)));
679+
if self.space_can_send(space_id, frame_space_1rtt).is_empty() {
680+
break;
681+
}
680682
}
681683
}
682684
}
@@ -691,7 +693,7 @@ impl Connection {
691693
// unexpectedly.
692694
buf.start_new_datagram_with_size(std::cmp::min(
693695
usize::from(INITIAL_MTU),
694-
buf.segment_size,
696+
buf.segment_size(),
695697
));
696698
}
697699
};
@@ -706,7 +708,7 @@ impl Connection {
706708
}
707709
}
708710

709-
debug_assert!(buf.buf_capacity - buf.len() >= MIN_PACKET_SPACE);
711+
debug_assert!(buf.datagram_max_offset() - buf.len() >= MIN_PACKET_SPACE);
710712

711713
//
712714
// From here on, we've determined that a packet will definitely be sent.
@@ -809,7 +811,7 @@ impl Connection {
809811

810812
// Send an off-path PATH_RESPONSE. Prioritized over on-path data to ensure that path
811813
// validation can occur while the link is saturated.
812-
if space_id == SpaceId::Data && buf.num_datagrams == 1 {
814+
if space_id == SpaceId::Data && buf.num_datagrams() == 1 {
813815
if let Some((token, remote)) = self.path_responses.pop_off_path(self.path.remote) {
814816
// `unwrap` guaranteed to succeed because `builder_storage` was populated just
815817
// above.
@@ -857,7 +859,7 @@ impl Connection {
857859
!(sent.is_ack_only(&self.streams)
858860
&& !can_send.acks
859861
&& can_send.other
860-
&& (buf.buf_capacity - builder.datagram_start)
862+
&& (buf.datagram_max_offset() - builder.datagram_start)
861863
== self.path.current_mtu() as usize
862864
&& self.datagrams.outgoing.is_empty()),
863865
"SendableFrames was {can_send:?}, but only ACKs have been written"
@@ -898,10 +900,10 @@ impl Connection {
898900
.mtud
899901
.poll_transmit(now, self.packet_number_filter.peek(&self.spaces[space_id]))?;
900902

901-
debug_assert_eq!(buf.num_datagrams, 0);
903+
debug_assert_eq!(buf.num_datagrams(), 0);
902904
buf.start_new_datagram_with_size(probe_size as usize);
903905

904-
debug_assert_eq!(buf.datagram_start, 0);
906+
debug_assert_eq!(buf.datagram_start_offset(), 0);
905907
let mut builder =
906908
PacketBuilder::new(now, space_id, self.rem_cids.active(), &mut buf, true, self)?;
907909

@@ -934,13 +936,13 @@ impl Connection {
934936
trace!(
935937
"sending {} bytes in {} datagrams",
936938
buf.len(),
937-
buf.num_datagrams
939+
buf.num_datagrams()
938940
);
939941
self.path.total_sent = self.path.total_sent.saturating_add(buf.len() as u64);
940942

941943
self.stats
942944
.udp_tx
943-
.on_sent(buf.num_datagrams as u64, buf.len());
945+
.on_sent(buf.num_datagrams() as u64, buf.len());
944946

945947
Some(Transmit {
946948
destination: self.path.remote,
@@ -950,9 +952,9 @@ impl Connection {
950952
} else {
951953
None
952954
},
953-
segment_size: match buf.num_datagrams {
955+
segment_size: match buf.num_datagrams() {
954956
1 => None,
955-
_ => Some(buf.segment_size),
957+
_ => Some(buf.segment_size()),
956958
},
957959
src_ip: self.local_ip,
958960
})
@@ -981,7 +983,7 @@ impl Connection {
981983
// sent once, immediately after migration, when the CID is known to be valid. Even
982984
// if a post-migration packet caused the CID to be retired, it's fair to pretend
983985
// this is sent first.
984-
debug_assert_eq!(buf.datagram_start, 0);
986+
debug_assert_eq!(buf.datagram_start_offset(), 0);
985987
let mut builder = PacketBuilder::new(now, SpaceId::Data, *prev_cid, buf, false, self)?;
986988
trace!("validating previous path with PATH_CHALLENGE {:08x}", token);
987989
buf.write(frame::FrameType::PATH_CHALLENGE);

quinn-proto/src/connection/packet_builder.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,11 @@ impl PacketBuilder {
149149
buffer.len() + (sample_size + 4).saturating_sub(number.len() + tag_len),
150150
partial_encode.start + dst_cid.len() + 6,
151151
);
152-
let max_size = buffer.buf_capacity - tag_len;
152+
let max_size = buffer.datagram_max_offset() - tag_len;
153153
debug_assert!(max_size >= min_size);
154154

155155
Some(Self {
156-
datagram_start: buffer.datagram_start,
156+
datagram_start: buffer.datagram_start_offset(),
157157
space: space_id,
158158
partial_encode,
159159
exact_number,

quinn-proto/src/connection/transmit_buf.rs

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,14 @@ pub(super) struct TransmitBuf<'a> {
3030
///
3131
/// Note that when coalescing packets this might be before the start of the current
3232
/// packet.
33-
pub(super) datagram_start: usize,
33+
datagram_start: usize,
3434
/// The maximum offset allowed to be used for the current datagram in the buffer
3535
///
3636
/// The first and last datagram in a batch are allowed to be smaller then the maximum
3737
/// size. All datagrams in between need to be exactly this size.
38-
pub(super) buf_capacity: usize,
38+
buf_capacity: usize,
3939
/// The maximum number of datagrams allowed to write into [`TransmitBuf::buf`]
40-
pub(super) max_datagrams: usize,
40+
max_datagrams: usize,
4141
/// The number of datagrams already (partially) written into the buffer
4242
///
4343
/// Incremented by a call to [`TransmitBuf::start_new_datagram`].
@@ -50,7 +50,7 @@ pub(super) struct TransmitBuf<'a> {
5050
/// For the first datagram this is set to the maximum size a datagram is allowed to be:
5151
/// the current path MTU. After the first datagram is finished this is reduced to the
5252
/// size of the first datagram and can no longer change.
53-
pub(super) segment_size: usize,
53+
segment_size: usize,
5454
}
5555

5656
impl<'a> TransmitBuf<'a> {
@@ -140,6 +140,42 @@ impl<'a> TransmitBuf<'a> {
140140
self.buf_capacity = self.buf.len();
141141
}
142142

143+
/// Returns the GSO segment size
144+
///
145+
/// This is also the maximum size datagrams are allowed to be. The first and last
146+
/// datagram in a batch are allowed to be smaller however. After the first datagram the
147+
/// segment size is clipped to the size of the first datagram.
148+
pub(super) fn segment_size(&self) -> usize {
149+
self.segment_size
150+
}
151+
152+
/// Returns the number of datagrams written into the buffer
153+
///
154+
/// The last datagram is not necessarily finished yet.
155+
pub(super) fn num_datagrams(&self) -> usize {
156+
self.num_datagrams
157+
}
158+
159+
/// Returns the maximum number of datagrams allowed to be written into the buffer
160+
pub(super) fn max_datagrams(&self) -> usize {
161+
self.max_datagrams
162+
}
163+
164+
/// Returns the start offset of the current datagram in the buffer
165+
///
166+
/// In other words, this offset contains the first byte of the current datagram.
167+
pub(super) fn datagram_start_offset(&self) -> usize {
168+
self.datagram_start
169+
}
170+
171+
/// Returns the maximum offset in the buffer allowed for the current datagram
172+
///
173+
/// The first and last datagram in a batch are allowed to be smaller then the maximum
174+
/// size. All datagrams in between need to be exactly this size.
175+
pub(super) fn datagram_max_offset(&self) -> usize {
176+
self.buf_capacity
177+
}
178+
143179
/// Returns `true` if the buffer did not have anything written into it
144180
pub(super) fn is_empty(&self) -> bool {
145181
self.len() == 0

0 commit comments

Comments
 (0)