feat: build out Transport
This commit is contained in:
1 parent
1f7895d714
commit
65f36973cf
1 file changed
+84
@@ -482,3 +482,87 @@ bool Transport::buildDatagram(Datagram& out) {
|
||||
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
|
||||
Reference in new issue
Block a user