Skip to content

Commit d2e3231

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 79c7e65 commit d2e3231

File tree

3 files changed

+65
-34
lines changed

3 files changed

+65
-34
lines changed

quinn-proto/src/connection/mod.rs

Lines changed: 29 additions & 29 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.buf_capacity >= buf.segment_size * buf.max_datagrams {
565+
if buf.datagram_max_offset() >= buf.segment_size() * 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,27 +640,28 @@ 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 {
664+
if buf.num_datagrams() == 1 && space_id == SpaceId::Data {
665665
// Now that we know the size of the first datagram, check whether
666666
// the data we planned to send will fit in the next segment. If
667667
// not, bails out and leave it for the next GSO batch. We can't
@@ -673,7 +673,7 @@ impl Connection {
673673
buf.clip_datagram_size();
674674

675675
let frame_space_1rtt = buf
676-
.segment_size
676+
.segment_size()
677677
.saturating_sub(self.predict_1rtt_overhead(Some(pn)));
678678
if self.space_can_send(space_id, frame_space_1rtt).is_empty() {
679679
break;
@@ -691,7 +691,7 @@ impl Connection {
691691
// unexpectedly.
692692
buf.start_new_datagram_with_size(std::cmp::min(
693693
usize::from(INITIAL_MTU),
694-
buf.segment_size,
694+
buf.segment_size(),
695695
));
696696
}
697697
};
@@ -706,7 +706,7 @@ impl Connection {
706706
}
707707
}
708708

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

711711
//
712712
// From here on, we've determined that a packet will definitely be sent.
@@ -809,7 +809,7 @@ impl Connection {
809809

810810
// Send an off-path PATH_RESPONSE. Prioritized over on-path data to ensure that path
811811
// validation can occur while the link is saturated.
812-
if space_id == SpaceId::Data && buf.num_datagrams == 1 {
812+
if space_id == SpaceId::Data && buf.num_datagrams() == 1 {
813813
if let Some((token, remote)) = self.path_responses.pop_off_path(self.path.remote) {
814814
// `unwrap` guaranteed to succeed because `builder_storage` was populated just
815815
// above.
@@ -857,7 +857,7 @@ impl Connection {
857857
!(sent.is_ack_only(&self.streams)
858858
&& !can_send.acks
859859
&& can_send.other
860-
&& (buf.buf_capacity - builder.datagram_start)
860+
&& (buf.datagram_max_offset() - builder.datagram_start)
861861
== self.path.current_mtu() as usize
862862
&& self.datagrams.outgoing.is_empty()),
863863
"SendableFrames was {can_send:?}, but only ACKs have been written"
@@ -898,10 +898,10 @@ impl Connection {
898898
.mtud
899899
.poll_transmit(now, self.packet_number_filter.peek(&self.spaces[space_id]))?;
900900

901-
debug_assert_eq!(buf.num_datagrams, 0);
901+
debug_assert_eq!(buf.num_datagrams(), 0);
902902
buf.start_new_datagram_with_size(probe_size as usize);
903903

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

@@ -934,13 +934,13 @@ impl Connection {
934934
trace!(
935935
"sending {} bytes in {} datagrams",
936936
buf.len(),
937-
buf.num_datagrams
937+
buf.num_datagrams()
938938
);
939939
self.path.total_sent = self.path.total_sent.saturating_add(buf.len() as u64);
940940

941941
self.stats
942942
.udp_tx
943-
.on_sent(buf.num_datagrams as u64, buf.len());
943+
.on_sent(buf.num_datagrams() as u64, buf.len());
944944

945945
Some(Transmit {
946946
destination: self.path.remote,
@@ -950,9 +950,9 @@ impl Connection {
950950
} else {
951951
None
952952
},
953-
segment_size: match buf.num_datagrams {
953+
segment_size: match buf.num_datagrams() {
954954
1 => None,
955-
_ => Some(buf.segment_size),
955+
_ => Some(buf.segment_size()),
956956
},
957957
src_ip: self.local_ip,
958958
})
@@ -981,7 +981,7 @@ impl Connection {
981981
// sent once, immediately after migration, when the CID is known to be valid. Even
982982
// if a post-migration packet caused the CID to be retired, it's fair to pretend
983983
// this is sent first.
984-
debug_assert_eq!(buf.datagram_start, 0);
984+
debug_assert_eq!(buf.datagram_start_offset(), 0);
985985
let mut builder = PacketBuilder::new(now, SpaceId::Data, *prev_cid, buf, false, self)?;
986986
trace!("validating previous path with PATH_CHALLENGE {:08x}", token);
987987
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: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ 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`]
4040
pub(super) max_datagrams: usize,
4141
/// The number of datagrams already (partially) written into the buffer
@@ -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> {
@@ -139,6 +139,37 @@ impl<'a> TransmitBuf<'a> {
139139
self.segment_size = self.buf.len();
140140
}
141141

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

0 commit comments

Comments
 (0)