}
hud.Display(res.block_types[player.GetInventorySlot() + 1]);
if (stat_timer.Hit()) {
- hud.UpdateNetStats(master);
+ hud.UpdateNetStats(master.NetStat());
}
hud.Update(dt);
--- /dev/null
+#ifndef BLANK_NET_CONGESTIONCONTROL_HPP_
+#define BLANK_NET_CONGESTIONCONTROL_HPP_
+
+#include <cstdint>
+#include <SDL_net.h>
+
+
+namespace blank {
+
+class CongestionControl {
+
+public:
+ CongestionControl();
+
+ /// packet loss as factor
+ float PacketLoss() const noexcept { return packet_loss; }
+ /// smooth average round trip time in milliseconds
+ float RoundTripTime() const noexcept { return rtt; }
+ /// estimated kilobytes transferred per second
+ float Upstream() const noexcept { return tx_kbps; }
+ /// estimated kilobytes received per second
+ float Downstream() const noexcept { return rx_kbps; }
+
+ void PacketSent(std::uint16_t) noexcept;
+ void PacketLost(std::uint16_t) noexcept;
+ void PacketReceived(std::uint16_t) noexcept;
+
+ void PacketIn(const UDPpacket &) noexcept;
+ void PacketOut(const UDPpacket &) noexcept;
+
+private:
+ void UpdatePacketLoss() noexcept;
+ void UpdateRTT(std::uint16_t) noexcept;
+ bool SamplePacket(std::uint16_t) const noexcept;
+ int HeadDiff(std::uint16_t) const noexcept;
+ void UpdateStats() noexcept;
+
+private:
+ const unsigned int packet_overhead;
+ const unsigned int sample_skip;
+
+ unsigned int packets_lost;
+ unsigned int packets_received;
+ float packet_loss;
+
+ Uint32 stamps[16];
+ std::size_t stamp_cursor;
+ std::uint16_t stamp_last;
+ float rtt;
+
+ Uint32 next_sample;
+ std::size_t tx_bytes;
+ std::size_t rx_bytes;
+ float tx_kbps;
+ float rx_kbps;
+
+};
+
+}
+
+#endif
#ifndef BLANK_NET_CONNECTIONHANDLER_HPP_
#define BLANK_NET_CONNECTIONHANDLER_HPP_
+#include "CongestionControl.hpp"
#include "Packet.hpp"
#include <SDL_net.h>
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; }
- /// estimated kilobytes transferred per second
- float Upstream() const noexcept { return tx_kbps; }
- /// estimated kilobytes received per second
- float Downstream() const noexcept { return rx_kbps; }
+ const CongestionControl &NetStat() const noexcept { return cc; }
void PacketSent(std::uint16_t) noexcept;
void PacketLost(std::uint16_t);
virtual void OnTimeout() { }
private:
- void UpdatePacketLoss() noexcept;
- void UpdateRTT(std::uint16_t) noexcept;
- bool SamplePacket(std::uint16_t) const noexcept;
- int HeadDiff(std::uint16_t) const noexcept;
- void UpdateStats() noexcept;
-
// called as soon as the remote end ack'd given packet
virtual void OnPacketReceived(std::uint16_t) { }
// called if the remote end probably didn't get given packet
virtual void On(const Packet::Message &) { }
private:
- unsigned int packets_lost;
- unsigned int packets_received;
- float packet_loss;
-
- Uint32 stamps[16];
- std::size_t stamp_cursor;
- std::uint16_t stamp_last;
- float rtt;
-
- Uint32 next_sample;
- std::size_t tx_bytes;
- std::size_t rx_bytes;
- float tx_kbps;
- float rx_kbps;
+ CongestionControl cc;
};
+#include "CongestionControl.hpp"
#include "Connection.hpp"
#include "ConnectionHandler.hpp"
#include "io.hpp"
constexpr size_t Packet::Message::MAX_LEN;
constexpr size_t Packet::Message::MAX_MESSAGE_LEN;
+
+CongestionControl::CongestionControl()
+// I know, I know, it's an estimate (about 20 for IPv4, 48 for IPv6)
+: packet_overhead(20)
+// only sample every eighth packet for measuring RTT
+, sample_skip(8)
+, packets_lost(0)
+, packets_received(0)
+, packet_loss(0.0f)
+, stamp_cursor(15)
+, stamp_last(0)
+, rtt(64.0f)
+, next_sample(1000)
+, tx_bytes(0)
+, rx_bytes(0)
+, tx_kbps(0.0f)
+, rx_kbps(0.0f) {
+ Uint32 now = SDL_GetTicks();
+ for (Uint32 &s : stamps) {
+ s = now;
+ }
+ next_sample += now;
+}
+
+void CongestionControl::PacketSent(uint16_t seq) noexcept {
+ if (!SamplePacket(seq)) {
+ return;
+ }
+ stamp_cursor = (stamp_cursor + 1) % 16;
+ stamps[stamp_cursor] = SDL_GetTicks();
+ stamp_last = seq;
+}
+
+void CongestionControl::PacketLost(uint16_t seq) noexcept {
+ ++packets_lost;
+ UpdatePacketLoss();
+ UpdateRTT(seq);
+}
+
+void CongestionControl::PacketReceived(uint16_t seq) noexcept {
+ ++packets_received;
+ UpdatePacketLoss();
+ UpdateRTT(seq);
+}
+
+void CongestionControl::UpdatePacketLoss() noexcept {
+ unsigned int packets_total = packets_lost + packets_received;
+ if (packets_total >= 256) {
+ packet_loss = float(packets_lost) / float(packets_total);
+ packets_lost = 0;
+ packets_received = 0;
+ }
+}
+
+void CongestionControl::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 CongestionControl::SamplePacket(std::uint16_t seq) const noexcept {
+ return seq % sample_skip == 0;
+}
+
+int CongestionControl::HeadDiff(std::uint16_t seq) const noexcept {
+ int16_t diff = int16_t(seq) - int16_t(stamp_last);
+ return diff / sample_skip;
+}
+
+void CongestionControl::PacketIn(const UDPpacket &pack) noexcept {
+ rx_bytes += pack.len + packet_overhead;
+ UpdateStats();
+}
+
+void CongestionControl::PacketOut(const UDPpacket &pack) noexcept {
+ tx_bytes += pack.len + packet_overhead;
+ UpdateStats();
+}
+
+void CongestionControl::UpdateStats() noexcept {
+ Uint32 now = SDL_GetTicks();
+ if (now >= next_sample) {
+ tx_kbps = float(tx_bytes) * (1.0f / 1024.0f);
+ rx_kbps = float(rx_bytes) * (1.0f / 1024.0f);
+ tx_bytes = 0;
+ rx_bytes = 0;
+ next_sample += 1000;
+ }
+}
+
+
Connection::Connection(const IPaddress &addr)
: handler(nullptr)
, addr(addr)
ConnectionHandler::ConnectionHandler()
-: packets_lost(0)
-, packets_received(0)
-, packet_loss(0.0f)
-, stamp_cursor(15)
-, stamp_last(0)
-, rtt(64.0f)
-, next_sample(1000)
-, tx_bytes(0)
-, rx_bytes(0)
-, tx_kbps(0.0f)
-, rx_kbps(0.0f) {
- Uint32 now = SDL_GetTicks();
- for (Uint32 &s : stamps) {
- s = now;
- }
- next_sample += now;
+: cc() {
+
}
void ConnectionHandler::PacketSent(uint16_t seq) noexcept {
- if (!SamplePacket(seq)) {
- return;
- }
- stamp_cursor = (stamp_cursor + 1) % 16;
- stamps[stamp_cursor] = SDL_GetTicks();
- stamp_last = seq;
+ cc.PacketSent(seq);
}
void ConnectionHandler::PacketLost(uint16_t seq) {
OnPacketLost(seq);
- ++packets_lost;
- UpdatePacketLoss();
- UpdateRTT(seq);
+ cc.PacketLost(seq);
}
void ConnectionHandler::PacketReceived(uint16_t seq) {
OnPacketReceived(seq);
- ++packets_received;
- UpdatePacketLoss();
- UpdateRTT(seq);
-}
-
-void ConnectionHandler::UpdatePacketLoss() noexcept {
- unsigned int packets_total = packets_lost + packets_received;
- if (packets_total >= 256) {
- packet_loss = float(packets_lost) / float(packets_total);
- packets_lost = 0;
- packets_received = 0;
- }
-}
-
-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;
+ cc.PacketReceived(seq);
}
void ConnectionHandler::PacketIn(const UDPpacket &pack) noexcept {
- rx_bytes += pack.len + 20; // I know, I know, it's an estimate (about 48 for IPv6)
- UpdateStats();
+ cc.PacketIn(pack);
}
void ConnectionHandler::PacketOut(const UDPpacket &pack) noexcept {
- tx_bytes += pack.len + 20;
- UpdateStats();
-}
-
-void ConnectionHandler::UpdateStats() noexcept {
- Uint32 now = SDL_GetTicks();
- if (now >= next_sample) {
- tx_kbps = float(tx_bytes) * (1.0f / 1024.0f);
- rx_kbps = float(rx_bytes) * (1.0f / 1024.0f);
- tx_bytes = 0;
- rx_bytes = 0;
- next_sample += 1000;
- }
+ cc.PacketOut(pack);
}
class Block;
class BlockTypeRegistry;
class Config;
-class ConnectionHandler;
+class CongestionControl;
class Environment;
class Font;
class Player;
void UpdateOrientation();
// net stats
- void UpdateNetStats(const ConnectionHandler &);
+ void UpdateNetStats(const CongestionControl &);
// message box
void PostMessage(const char *);
#include "../graphics/Viewport.hpp"
#include "../io/TokenStreamReader.hpp"
#include "../model/bounds.hpp"
-#include "../net/ConnectionHandler.hpp"
+#include "../net/CongestionControl.hpp"
#include "../world/BlockLookup.hpp"
#include "../world/World.hpp"
#include "../world/WorldManipulator.hpp"
}
-void HUD::UpdateNetStats(const ConnectionHandler &conn) {
+void HUD::UpdateNetStats(const CongestionControl &stat) {
+ if (!config.video.debug) return;
+
std::stringstream s;
s << std::fixed << std::setprecision(1)
- << "TX: " << conn.Upstream()
- << "KB/s, RX: " << conn.Downstream() << "KB/s";
+ << "TX: " << stat.Upstream()
+ << "KB/s, RX: " << stat.Downstream() << "KB/s";
bandwidth_text.Set(env.assets.small_ui_font, s.str());
s.str("");
- s << "RTT: " << conn.RoundTripTime() << "ms";
+ s << "RTT: " << stat.RoundTripTime() << "ms";
rtt_text.Set(env.assets.small_ui_font, s.str());
s.str("");
- s << "Packet loss: " << (conn.PacketLoss() * 100.0f) << "%";
+ s << "Packet loss: " << (stat.PacketLoss() * 100.0f) << "%";
packet_loss_text.Set(env.assets.small_ui_font, s.str());
show_net = true;