feat: build out Transport

This commit is contained in:
dualfroz committed 2026-09-09 23:07:17 +02:00
1 parent 1f7895d714
commit 65f36973cf
1 file changed
+84
+84
View File
@@ -482,3 +482,87 @@ bool Transport::buildDatagram(Datagram& out) {
unreliable.dropOutgoing(); unreliable.dropOutgoing();
} }
return !out.fragments.empty();
}
void Transport::flush(uint64_t tick) {
for (std::size_t i = 0; i < inFlight.size();) {
if (tick - inFlight[i].sentTick < config.retransmitTimeoutTicks) {
++i;
continue;
}
++statistics.datagramsLost;
for (uint64_t key : inFlight[i].reliableKeys) {
if (reliable.fragment(key) == nullptr) continue;
reliable.markLost(key);
++statistics.retransmitted;
}
inFlight.erase(inFlight.begin() + static_cast<std::ptrdiff_t>(i));
}
bool sentAnything = false;
while (inFlight.size() < config.sendWindow) {
Datagram datagram;
if (!buildDatagram(datagram)) break;
datagram.sequence = nextSequence++;
datagram.ackLatest = remoteLatest;
datagram.ackHistory = remoteHistory;
datagram.ackValid = anyReceived;
InFlightDatagram record;
record.sequence = datagram.sequence;
record.sentTick = tick;
for (const Datagram::Fragment& piece : datagram.fragments)
if (piece.reliable)
record.reliableKeys.push_back(
ReliableChannel::fragmentKey(piece.messageId, piece.fragmentIndex));
inFlight.push_back(std::move(record));
ByteWriter writer;
datagram.encode(writer);
++statistics.datagramsSent;
statistics.bytesSent += writer.size();
link->send(endpoint, writer.bytes(), tick);
sentAnything = true;
}
// A pure ack keeps the peer's window moving when traffic is one-directional.
// It carries no fragments, so it cannot itself provoke another ack.
if (!sentAnything && ackPending) {
Datagram datagram;
datagram.sequence = nextSequence++;
datagram.ackLatest = remoteLatest;
datagram.ackHistory = remoteHistory;
datagram.ackValid = anyReceived;
ByteWriter writer;
datagram.encode(writer);
++statistics.datagramsSent;
statistics.bytesSent += writer.size();
link->send(endpoint, writer.bytes(), tick);
}
ackPending = false;
}
void Transport::update(uint64_t tick) {
pump(tick);
flush(tick);
}
bool Transport::popReliable(ByteBuffer& out) {
if (!reliable.popDelivered(out)) return false;
++statistics.messagesDelivered;
return true;
}
bool Transport::popUnreliable(ByteBuffer& out) {
if (!unreliable.popDelivered(out)) return false;
++statistics.messagesDelivered;
return true;
}
std::size_t Transport::pendingOutgoingCount() const {
return reliable.readyFragmentCount() + unreliable.outgoingFragmentCount();
}
} // namespace vf