in quic/s2n-quic-platform/src/socket/io/tx.rs [392:453]
fn push<M>(&mut self, message: M) -> Result<tx::Outcome, tx::Error>
where
M: tx::Message<Handle = Self::Handle>,
{
// first try to write a GSO payload, if supported
let mut message = match self.try_gso(message)? {
Ok(outcome) => return Ok(outcome),
Err(message) => message,
};
// find the next free entry, if any
let entry = loop {
let channel = self
.channels
.get_mut(self.channel_index)
.ok_or(tx::Error::AtCapacity)?;
if let Some(entry) = channel.data().get_mut(self.message_index) {
break entry;
} else {
// this channel is out of free messages so flush it and move to the next channel
self.flush_channel();
self.channel_index += 1;
};
};
// prepare the entry for writing and reset all of the fields
unsafe {
// Safety: the entries should have been allocated with the MaxMtu
entry.reset(self.max_mtu);
}
// query the values that we use for GSO before we write the message to the entry
let handle = *message.path_handle();
let ecn = message.ecn();
let can_gso = message.can_gso(self.max_mtu, 0);
// write the message to the entry
let payload_len = entry.tx_write(message)?;
// if GSO is supported and we are allowed to have additional segments, store the GSO state
// for another potential message to be written later
if T::SUPPORTS_GSO && self.max_segments > 1 && can_gso {
self.gso_segment = Some(GsoSegment {
handle,
ecn,
count: 1,
size: payload_len,
});
} else {
// otherwise, release the message to the consumer
self.release_message();
}
// let the caller know how big the payload was
let outcome = tx::Outcome {
len: payload_len,
index: 0,
};
Ok(outcome)
}