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();
|
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