From: Daniel Karbach Date: Mon, 26 Oct 2015 16:39:33 +0000 (+0100) Subject: measure packet round trip time X-Git-Url: http://git.localhorst.tv/?a=commitdiff_plain;h=c256dca7c6ca2c7f8eeffae53c02fe62bd892198;p=blank.git measure packet round trip time --- diff --git a/src/net/ConnectionHandler.hpp b/src/net/ConnectionHandler.hpp index 77bcd7b..be01d10 100644 --- a/src/net/ConnectionHandler.hpp +++ b/src/net/ConnectionHandler.hpp @@ -13,8 +13,12 @@ class ConnectionHandler { public: ConnectionHandler(); + /// packet loss as factor float PacketLoss() const noexcept { return packet_loss; } + /// smooth average round trip time in milliseconds + float RoundTripTime() const noexcept { return rtt; } + void PacketSent(std::uint16_t); void PacketLost(std::uint16_t); void PacketReceived(std::uint16_t); @@ -24,6 +28,9 @@ public: private: void UpdatePacketLoss() noexcept; + void UpdateRTT(std::uint16_t) noexcept; + bool SamplePacket(std::uint16_t) const noexcept; + int HeadDiff(std::uint16_t) const noexcept; // called as soon as the remote end ack'd given packet virtual void OnPacketReceived(std::uint16_t) { } @@ -49,6 +56,11 @@ private: unsigned int packets_received; float packet_loss; + Uint32 stamps[16]; + std::size_t stamp_cursor; + std::uint16_t stamp_last; + float rtt; + }; } diff --git a/src/net/net.cpp b/src/net/net.cpp index 9b50479..59176aa 100644 --- a/src/net/net.cpp +++ b/src/net/net.cpp @@ -84,6 +84,10 @@ uint16_t Connection::Send(UDPpacket &udp_pack, UDPsocket sock) { throw NetError("SDLNet_UDP_Send"); } + if (HasHandler()) { + Handler().PacketSent(seq); + } + FlagSend(); return seq; } @@ -151,20 +155,37 @@ uint16_t Connection::SendPing(UDPpacket &udp_pack, UDPsocket sock) { ConnectionHandler::ConnectionHandler() : packets_lost(0) , packets_received(0) -, packet_loss(0.0f) { +, packet_loss(0.0f) +, stamp_cursor(15) +, stamp_last(0) +, rtt(64.0f) { + Uint32 now = SDL_GetTicks(); + for (Uint32 &s : stamps) { + s = now; + } +} +void ConnectionHandler::PacketSent(uint16_t seq) { + if (!SamplePacket(seq)) { + return; + } + stamp_cursor = (stamp_cursor + 1) % 16; + stamps[stamp_cursor] = SDL_GetTicks(); + stamp_last = seq; } void ConnectionHandler::PacketLost(uint16_t seq) { OnPacketLost(seq); ++packets_lost; UpdatePacketLoss(); + UpdateRTT(seq); } void ConnectionHandler::PacketReceived(uint16_t seq) { OnPacketReceived(seq); ++packets_received; UpdatePacketLoss(); + UpdateRTT(seq); } void ConnectionHandler::UpdatePacketLoss() noexcept { @@ -176,6 +197,27 @@ void ConnectionHandler::UpdatePacketLoss() noexcept { } } +void ConnectionHandler::UpdateRTT(std::uint16_t seq) noexcept { + if (!SamplePacket(seq)) return; + int diff = HeadDiff(seq); + if (diff > 0 || diff < -15) { + // packet outside observed time frame + return; + } + int cur_rtt = SDL_GetTicks() - stamps[(stamp_cursor + diff + 16) % 16]; + rtt += (cur_rtt - rtt) * 0.1f; +} + +bool ConnectionHandler::SamplePacket(std::uint16_t seq) const noexcept { + // only sample every eighth packet + return seq % 8 == 0; +} + +int ConnectionHandler::HeadDiff(std::uint16_t seq) const noexcept { + int16_t diff = int16_t(seq) - int16_t(stamp_last); + return diff / 8; +} + ostream &operator <<(ostream &out, const IPaddress &addr) { const unsigned char *host = reinterpret_cast(&addr.host);