150 lines
4.8 KiB
C++
150 lines
4.8 KiB
C++
#pragma once
|
|
|
|
/** A peer of a bound (server) instance of UdpVpn */
|
|
|
|
#include <netinet/in.h>
|
|
#include <bitset>
|
|
#include <time.h>
|
|
#include "util.hpp"
|
|
#include "VpnPacket.hpp"
|
|
#include "congestion_control.hpp"
|
|
|
|
class UdpVpn;
|
|
|
|
const int PACKET_LOSS_WINDOW = 128, PACKET_LOST_AFTER = 8;
|
|
|
|
class PacketLossLogger {
|
|
public:
|
|
PacketLossLogger();
|
|
void log_packet(uint32_t seqno);
|
|
double get_loss_rate() const {
|
|
return (double)(_win_start_losses - _last_window_losses)
|
|
/ (double)PACKET_LOSS_WINDOW;
|
|
}
|
|
|
|
const std::bitset<PACKET_LOST_AFTER> get_received_ahead() const {
|
|
return _received_ahead;
|
|
}
|
|
|
|
uint32_t get_cur_seqno() const { return _cur_seqno; }
|
|
unsigned int get_tot_losses() const { return _tot_losses; }
|
|
|
|
private:
|
|
void reboot(); ///< completely reset the internal state
|
|
|
|
/// roll loss window values if `_cur_seqno + offs` is a window start.
|
|
void maybe_start_window(int offs=0);
|
|
|
|
std::bitset<PACKET_LOST_AFTER> _received_ahead;
|
|
uint32_t _cur_seqno;
|
|
unsigned int _tot_losses;
|
|
unsigned int _last_window_losses, _win_start_losses;
|
|
};
|
|
|
|
/** Round-trip time logger. All timestamps/delays are in microseconds. */
|
|
class RTTLogger {
|
|
public:
|
|
RTTLogger();
|
|
uint32_t avg_rtt() const { return _avg_rtt; }
|
|
uint32_t cur_rtt() const { return _cur_rtt; }
|
|
struct timespec get_last_update() const {
|
|
return _last_update;
|
|
}
|
|
|
|
/** Checks whether an update is due.
|
|
* If soon is true, divides the inter-update delay by 2.
|
|
*/
|
|
bool update_due(bool soon=false) const;
|
|
|
|
void log(const VpnTlvRTTA& rtt_answer);
|
|
|
|
private:
|
|
uint32_t _avg_rtt, _cur_rtt;
|
|
static const double EXP_AVG_FACTOR;
|
|
|
|
unsigned int _update_delay; // in ms
|
|
static const unsigned int BASE_UPDATE_DELAY; // in ms
|
|
struct timespec _last_update;
|
|
};
|
|
|
|
class VpnPeer {
|
|
public:
|
|
class NetError : public MsgException {
|
|
public:
|
|
NetError(
|
|
const std::string& msg,
|
|
int code=0,
|
|
bool is_perror=false)
|
|
: MsgException(msg, code, is_perror) {}
|
|
};
|
|
|
|
/// Logs the loss reports sent by the remote peer
|
|
struct LossReports {
|
|
uint32_t prev_seqno, last_seqno;
|
|
uint32_t prev_losses, last_losses;
|
|
|
|
double loss_rate() const {
|
|
return (double)(last_losses - prev_losses)
|
|
/ (double)(last_seqno - prev_seqno);
|
|
}
|
|
};
|
|
|
|
VpnPeer(UdpVpn* vpn, const sockaddr_in6& ext_addr,
|
|
const in6_addr& int_addr);
|
|
|
|
const sockaddr_in6& get_ext_addr() const { return _ext_addr; }
|
|
const in6_addr& get_int_addr() const { return _int_addr; }
|
|
|
|
void set_int_addr(const in6_addr& int_addr);
|
|
|
|
const PacketLossLogger& get_loss_logger() const { return _packet_loss; }
|
|
const RTTLogger& get_rtt() const { return _rtt; }
|
|
const LossReports& get_loss_reports() const { return _loss_reports; }
|
|
const CongestionController& get_congestion_controller() const {
|
|
return _congestion_controller; }
|
|
|
|
void tick(); ///< periodic actions, triggered every UdpVpn tick
|
|
|
|
void log_rtta(const VpnTlvRTTA& rtta) { _rtt.log(rtta); }
|
|
void log_loss_report(const VpnTlvLossReport& loss_rep);
|
|
|
|
size_t write(const char* data, size_t len);
|
|
size_t write(const VpnPacket& packet);
|
|
|
|
uint32_t peek_next_seqno() const { return _next_send_seqno; }
|
|
uint32_t next_seqno() { return _next_send_seqno++; }
|
|
|
|
uint64_t get_tot_bytes_sent() const { return _tot_bytes_sent; }
|
|
double get_outbound_byte_rate() const { return _outbound_byte_rate; }
|
|
|
|
void got_inbound_packet(const VpnPacket& packet);
|
|
|
|
/* === Control protocol === */
|
|
/// Send a control packet if there is data to be sent
|
|
bool send_control_packet();
|
|
|
|
/// Append a RTTA for the given RTTQ to the next control packet
|
|
void make_rtta_for(const VpnTlvRTTQ& rttq);
|
|
|
|
private: // meth
|
|
void make_loss_report(); ///< Add a loss report to the next control packet
|
|
void cycle_next_control(); ///< Generate a fresh next control packet
|
|
|
|
private:
|
|
UdpVpn* _vpn;
|
|
sockaddr_in6 _ext_addr;
|
|
in6_addr _int_addr;
|
|
uint32_t _next_send_seqno;
|
|
|
|
uint64_t _tot_bytes_sent, _prev_tot_bytes_sent;
|
|
double _outbound_byte_rate;
|
|
|
|
struct timespec _prev_tick_time;
|
|
|
|
PacketLossLogger _packet_loss;
|
|
LossReports _loss_reports;
|
|
RTTLogger _rtt;
|
|
CongestionController _congestion_controller;
|
|
|
|
std::unique_ptr<VpnControlPacket> _next_control_packet;
|
|
};
|