in quic/s2n-quic-transport/src/sync/data_sender.rs [380:464]
fn on_transmit_impl<W: WriteContext>(
&mut self,
writer_context: Writer::Context,
context: &mut W,
) -> Result<(), OnTransmitError> {
let constraint = context.transmission_constraint();
let mut transmitted_lost = false;
// try to retransmit any lost ranges first
if constraint.can_retransmit() {
transmitted_lost = self.transmissions.transmit_set(
&self.buffer,
&mut self.lost,
&mut self.state,
writer_context,
context,
)?;
}
let is_blocked = self.flow_controller().is_blocked();
// try to transmit the enqueued ranges
let total_len = self.buffer.total_len();
let starting_transmission_offset = self.transmission_offset;
if !is_blocked && constraint.can_transmit() && self.transmission_offset < total_len {
let mut viewer = self.buffer.viewer();
self.transmission_offset = self
.transmissions
.transmit_interval(
&mut viewer,
(self.transmission_offset..total_len).into(),
&mut self.state,
writer_context,
context,
)?
.end_exclusive();
}
if Writer::WRITES_FIN && self.state.can_transmit_fin(constraint, is_blocked) {
self.transmissions.transmit_fin(
&self.buffer,
&mut self.state,
writer_context,
context,
)?;
}
// If the current transmission is a loss recovery probe, we can include some already
// transmitted, unacknowledged data in the probe packet since there is a higher likelihood
// this data has been lost. If lost data has already been written to the packet, we
// skip this feature as an optimization to avoid having to filter out already written
// lost data. Since it is unlikely there is lost data requiring retransmission at the
// same time as a probe transmission is being sent, this optimization does not have
// much impact on the effectiveness of this feature.
let retransmit_unacked_data_in_probe = Writer::RETRANSMIT_IN_PROBE
&& context.transmission_mode().is_loss_recovery_probing()
&& !transmitted_lost;
if retransmit_unacked_data_in_probe {
let mut viewer = self.buffer.viewer();
for interval in self.pending.intervals() {
if interval.start_inclusive() >= starting_transmission_offset {
// Don't write data we've already written to this packet
break;
}
let interval_end = interval.end_exclusive().min(starting_transmission_offset);
self.transmissions.transmit_interval(
&mut viewer,
(interval.start_inclusive()..interval_end).into(),
&mut self.state,
writer_context,
context,
)?;
}
}
self.check_integrity();
Ok(())
}