diff --git a/UdpVpn.cpp b/UdpVpn.cpp index 22d8776..7d35f20 100644 --- a/UdpVpn.cpp +++ b/UdpVpn.cpp @@ -8,13 +8,15 @@ #include #include #include +#include #include "ip_header.hpp" static const size_t VPN_MTU = 1460; // TODO determine this -- issue #3 UdpVpn::UdpVpn() - : _stopped(false), _vpn_mtu(VPN_MTU), _tun_dev("cvpn%d"), _peer(nullptr) + : _stopped(false), _dump_requested(false), _vpn_mtu(VPN_MTU), + _tun_dev("cvpn%d"), _peer(nullptr) { _tun_dev.set_mtu(VpnPacket::get_tunnelled_mtu(_vpn_mtu)); _socket = socket(AF_INET6, SOCK_DGRAM, 0); @@ -42,6 +44,11 @@ void UdpVpn::run() { poll_fds[1].events = POLLIN; while(!_stopped) { + if(_dump_requested) { + dump_state(); + _dump_requested = false; + } + rc = poll(poll_fds, nfds, -1); if(rc < 0) { @@ -75,7 +82,7 @@ size_t UdpVpn::read_from_tun(char* buffer, size_t len) { return _tun_dev.read(buffer, len); } -size_t UdpVpn::read_from_tun(TunnelledPacket& packet) { +size_t UdpVpn::read_from_tun(VpnDataPacket& packet) { size_t payload_space = packet.get_payload_space(); size_t nread = read_from_tun(packet.get_payload(), payload_space); packet.set_payload_size(nread); @@ -136,9 +143,8 @@ size_t UdpVpn::transmit_to_peer(VpnPacket& packet) { } void UdpVpn::receive_from_tun() { - VpnPacket packet(_vpn_mtu); - TunnelledPacket tunnelled = TunnelledPacket::create(packet); - size_t nread = read_from_tun(tunnelled); + VpnDataPacket packet(_vpn_mtu, false); + size_t nread = read_from_tun(packet); if(nread == 0) return; @@ -149,8 +155,8 @@ void UdpVpn::receive_from_tun() { packet.set_peer(_peer.get()); kdebugf("Transmitting %s -> %s, size %d\n", - format_address(tunnelled.get_ipv6_header().source.s6_addr), - format_address(tunnelled.get_ipv6_header().dest.s6_addr), + format_address(packet.get_ipv6_header().source.s6_addr), + format_address(packet.get_ipv6_header().dest.s6_addr), nread); packet.prepare_for_sending(); @@ -158,7 +164,7 @@ void UdpVpn::receive_from_tun() { } void UdpVpn::receive_from_udp() { - VpnPacket packet(_vpn_mtu); + VpnPacket packet(_vpn_mtu, true); sockaddr_in6 peer_ext_addr; size_t nread = read_from_udp(packet, peer_ext_addr); if(nread == 0) @@ -167,32 +173,41 @@ void UdpVpn::receive_from_udp() { // If we don't have a peer yet -- we're just setting the peer to nullptr. packet.set_peer(_peer.get()); - for(VpnPacketTLV tlv=packet.first_tlv(); - !tlv.past_the_end(); - tlv.seek_next_tlv()) - { - switch(tlv.get_type()) { - case VpnPacket::PAYLOAD_TYPE_TUNNELLED: - { - TunnelledPacket tunnelled(tlv); - acquire_peer(tunnelled, peer_ext_addr); - receive_tunnelled_tlv(tunnelled); - } - break; + if(packet.is_control()) { + VpnControlPacket ctrl_packet(std::move(packet)); - case VpnPacket::PAYLOAD_TYPE_UNDEF: - default: - debugf("#%d+%lu: ignoring TLV with bad type %d.\n", - packet.get_seqno(), tlv.get_offset(), - tlv.get_type()); - break; + for(VpnPacketTLV tlv=ctrl_packet.first_tlv(); + !tlv.past_the_end(); + tlv.seek_next_tlv()) + { + switch(tlv.get_type()) { + case VpnPacketTLV::PAYLOAD_TYPE_UNDEF: + default: + debugf("#%d+%lu: ignoring TLV with bad type %d.\n", + ctrl_packet.get_seqno(), tlv.get_offset(), + tlv.get_type()); + break; + } } + } else { + VpnDataPacket data_packet(std::move(packet)); + acquire_peer(data_packet, peer_ext_addr); + receive_tunnelled_tlv(data_packet); } } -void UdpVpn::receive_tunnelled_tlv(TunnelledPacket& packet) { +void UdpVpn::receive_tunnelled_tlv(VpnDataPacket& packet) { // Reinject into tun - kdebugf("Reinjecting tunnelled packet of size %d\n", - packet.get_payload_size()); + kdebugf("Reinjecting tunnelled packet of size %d [#%ld, TS=%ld μs]\n", + packet.get_payload_size(), + packet.get_seqno(), + packet.get_sending_timestamp()); _tun_dev.write(packet.get_payload(), packet.get_payload_size()); } + +void UdpVpn::dump_state() const { + printf("====== State dump ======\n"); + printf("Packet loss rate: %.0lf%%\n", + round(_peer->get_loss_logger().get_loss_rate() * 100)); + printf("==== End state dump ====\n"); +} diff --git a/UdpVpn.hpp b/UdpVpn.hpp index fa98b8c..55b835a 100644 --- a/UdpVpn.hpp +++ b/UdpVpn.hpp @@ -41,13 +41,16 @@ class UdpVpn { // Stop the server. Can be called from an interrupt. void stop() { _stopped = true; } + // A state dump has been requested + void dump_requested() { _dump_requested = true; } + protected: virtual void acquire_peer( - TunnelledPacket& packet, + VpnDataPacket& packet, const sockaddr_in6& peer_ext_addr) = 0; size_t read_from_tun(char* buffer, size_t len); - size_t read_from_tun(TunnelledPacket& packet); + size_t read_from_tun(VpnDataPacket& packet); size_t read_from_udp(char* buffer, size_t len, sockaddr_in6& peer_addr); size_t read_from_udp(VpnPacket& packet, sockaddr_in6& peer_addr); @@ -56,10 +59,12 @@ class UdpVpn { void receive_from_tun(); void receive_from_udp(); - void receive_tunnelled_tlv(TunnelledPacket& packet); + void receive_tunnelled_tlv(VpnDataPacket& packet); + + void dump_state() const; int _socket; - bool _stopped; + bool _stopped, _dump_requested; size_t _vpn_mtu; diff --git a/UdpVpnClient.cpp b/UdpVpnClient.cpp index 0363c0b..4f452ea 100644 --- a/UdpVpnClient.cpp +++ b/UdpVpnClient.cpp @@ -8,7 +8,7 @@ UdpVpnClient::UdpVpnClient(const struct sockaddr_in6& server) : UdpVpn() { } void UdpVpnClient::acquire_peer( - TunnelledPacket& packet, + VpnDataPacket& packet, const sockaddr_in6&) { if(!packet.parse_as_ipv6()) diff --git a/UdpVpnClient.hpp b/UdpVpnClient.hpp index f3d371b..7b07c87 100644 --- a/UdpVpnClient.hpp +++ b/UdpVpnClient.hpp @@ -8,6 +8,6 @@ class UdpVpnClient: public UdpVpn { protected: virtual void acquire_peer( - TunnelledPacket& packet, + VpnDataPacket& packet, const sockaddr_in6& peer_ext_addr); }; diff --git a/UdpVpnServer.cpp b/UdpVpnServer.cpp index bb8a060..8592cee 100644 --- a/UdpVpnServer.cpp +++ b/UdpVpnServer.cpp @@ -16,7 +16,7 @@ UdpVpnServer::UdpVpnServer(const struct in6_addr& bind_addr6, in_port_t port) } void UdpVpnServer::acquire_peer( - TunnelledPacket& packet, + VpnDataPacket& packet, const sockaddr_in6& peer_ext_addr) { if(_peer) @@ -28,7 +28,7 @@ void UdpVpnServer::acquire_peer( const in6_addr& peer_inner_addr = packet.get_ipv6_header().source; _peer = std::make_unique(this, peer_ext_addr, peer_inner_addr); - packet.get_packet().set_peer(_peer.get()); + packet.set_peer(_peer.get()); debugf("Got new peer %s:%d -- %s\n", format_address(peer_ext_addr.sin6_addr.s6_addr), diff --git a/UdpVpnServer.hpp b/UdpVpnServer.hpp index 664f0f4..841070c 100644 --- a/UdpVpnServer.hpp +++ b/UdpVpnServer.hpp @@ -11,7 +11,7 @@ class UdpVpnServer: public UdpVpn { UdpVpnServer(const struct in6_addr& bind_addr6, in_port_t port); protected: virtual void acquire_peer( - TunnelledPacket& packet, + VpnDataPacket& packet, const sockaddr_in6& peer_ext_addr); void bind(const struct in6_addr& bind_addr6, in_port_t port); diff --git a/VpnPacket.cpp b/VpnPacket.cpp index 2f4c0a4..a007eca 100644 --- a/VpnPacket.cpp +++ b/VpnPacket.cpp @@ -5,7 +5,7 @@ #include const size_t VpnPacket::VPN_HEADER_BYTES = 8; -const size_t VpnPacket::TLV_HEADER_BYTES = 3; +const size_t VpnControlPacket::TLV_HEADER_BYTES = 3; static const size_t OUTER_HEADERS_BYTES = 40 /* IPv6 header */ + 8 /* UDP header */; @@ -13,40 +13,67 @@ static const size_t OUTER_HEADERS_BYTES = static const int DATA_SEQNO_POS = 0, + DATA_CTRLBIT_POS = 4, DATA_TIMESTAMP_POS = 4; -VpnPacket::VpnPacket(size_t mtu) - : _peer(nullptr), _data_space(mtu-OUTER_HEADERS_BYTES), +VpnPacket::VpnPacket(size_t mtu, bool inbound) + : _peer(nullptr), _inbound(inbound), _data_space(mtu-OUTER_HEADERS_BYTES), _data_size(VPN_HEADER_BYTES), _reception_timestamp(0) { - _data = new char[mtu - OUTER_HEADERS_BYTES]; + _data = std::unique_ptr(new char[mtu - OUTER_HEADERS_BYTES]); } -VpnPacket::~VpnPacket() { - delete[] _data; -} +VpnPacket::~VpnPacket() {} -VpnPacketTLV VpnPacket::first_tlv() { - return VpnPacketTLV(*this, 0); -} +VpnPacket::VpnPacket(VpnPacket&& move_from) : + _peer(move_from._peer), + _inbound(move_from._inbound), + _data(std::move(move_from._data)), + _data_space(move_from._data_space), + _data_size(move_from._data_size), + _reception_timestamp(move_from._reception_timestamp) +{} size_t VpnPacket::get_tunnelled_mtu(size_t udp_mtu) { - return udp_mtu - OUTER_HEADERS_BYTES - VPN_HEADER_BYTES - TLV_HEADER_BYTES; + return udp_mtu - OUTER_HEADERS_BYTES - VPN_HEADER_BYTES; +} + +void VpnPacket::set_peer(VpnPeer* peer) { + _peer = peer; + if(_peer && _inbound) + _peer->got_inbound_packet(*this); } uint32_t VpnPacket::get_seqno() const { - return *(uint32_t*)(_data + DATA_SEQNO_POS); + return ntohl(*(uint32_t*)(_data.get() + DATA_SEQNO_POS)); } uint32_t VpnPacket::get_sending_timestamp() const { - return *(uint32_t*)(_data + DATA_TIMESTAMP_POS); + return ntohl( + *(uint32_t*)(_data.get() + DATA_TIMESTAMP_POS) & 0x7fffffffUL + ); +} + +bool VpnPacket::is_control() const { + return *(unsigned char*)(_data.get() + DATA_CTRLBIT_POS) & 0x80; +} + +void VpnPacket::set_control(bool is_control) { + unsigned char* ctrl_field = + (unsigned char*) (_data.get() + DATA_CTRLBIT_POS); + *ctrl_field &= 0x7f; + if(is_control) + *ctrl_field |= 0x80; } void VpnPacket::prepare_for_sending() { - *(uint32_t*)(_data + DATA_SEQNO_POS) = next_seqno(); - *(uint32_t*)(_data + DATA_TIMESTAMP_POS) = - std::chrono::time_point_cast( - std::chrono::steady_clock::now()).time_since_epoch().count(); + uint32_t* ts_field = (uint32_t*) (_data.get() + DATA_TIMESTAMP_POS); + *ts_field &= 0x80000000UL; + *(uint32_t*)(_data.get() + DATA_SEQNO_POS) = htonl(next_seqno()); + *ts_field |= + htonl((std::chrono::time_point_cast( + std::chrono::steady_clock::now()).time_since_epoch().count()) + & 0x7fffffffUL); } void VpnPacket::upon_reception() { @@ -61,8 +88,35 @@ uint32_t VpnPacket::next_seqno() { return _peer->next_seqno(); } +VpnControlPacket::VpnControlPacket(size_t mtu, bool inbound) + : VpnPacket(mtu, inbound) +{ + set_control(true); +} -VpnPacketTLV::VpnPacketTLV(VpnPacket& packet, size_t payload_offset) +VpnControlPacket::VpnControlPacket(VpnPacket&& move_from) + : VpnPacket(std::move(move_from)) +{} + +VpnPacketTLV VpnControlPacket::first_tlv() { + return VpnPacketTLV(*this, 0); +} + +VpnDataPacket::VpnDataPacket(size_t mtu, bool inbound) + : VpnPacket(mtu, inbound), _ipv6_parsed(false) +{ + set_control(false); +} + +VpnDataPacket::VpnDataPacket(VpnPacket&& move_from) + : VpnPacket(std::move(move_from)), _ipv6_parsed(false) +{} + +bool VpnDataPacket::parse_as_ipv6() { + return parse_ipv6_header(get_payload(), get_payload_size(), _ipv6_header); +} + +VpnPacketTLV::VpnPacketTLV(VpnControlPacket& packet, size_t payload_offset) : _packet(packet), _tlv_pos(payload_offset) {} @@ -71,10 +125,10 @@ VpnPacketTLV::VpnPacketTLV(const VpnPacketTLV& other) : {} VpnPacketTLV VpnPacketTLV::create( - VpnPacket& packet, VpnPacket::PayloadType type) + VpnControlPacket& packet, VpnPacketTLV::PayloadType type) { VpnPacketTLV tlv = VpnPacketTLV(packet, packet.get_payload_size()); - packet.increase_payload_size(VpnPacket::TLV_HEADER_BYTES); + packet.increase_payload_size(VpnControlPacket::TLV_HEADER_BYTES); char* data = tlv.get_data(); data[0] = type; @@ -89,7 +143,8 @@ VpnPacketTLV VpnPacketTLV::next_tlv() { } void VpnPacketTLV::seek_next_tlv() { - _tlv_pos = _tlv_pos + VpnPacket::TLV_HEADER_BYTES + get_payload_size(); + _tlv_pos = + _tlv_pos + VpnControlPacket::TLV_HEADER_BYTES + get_payload_size(); } uint16_t VpnPacketTLV::get_payload_size() const { @@ -108,25 +163,9 @@ uint16_t VpnPacketTLV::get_payload_space() const { + get_payload_size(); } -VpnPacket::PayloadType VpnPacketTLV::get_type() const { - return (VpnPacket::PayloadType)(*(uint8_t*)(get_data())); +VpnPacketTLV::PayloadType VpnPacketTLV::get_type() const { + return (PayloadType)(*(uint8_t*)(get_data())); } -void VpnPacketTLV::set_type(VpnPacket::PayloadType type) { +void VpnPacketTLV::set_type(VpnPacketTLV::PayloadType type) { *(uint8_t*)(get_data()) = (uint8_t) type; } - -TunnelledPacket::TunnelledPacket(VpnPacket& packet, size_t payload_offset) - : VpnPacketTLV(packet, payload_offset) -{} - -TunnelledPacket::TunnelledPacket(const VpnPacketTLV& copy) - : VpnPacketTLV(copy._packet, copy._tlv_pos) -{} - -TunnelledPacket TunnelledPacket::create(VpnPacket& packet) { - return VpnPacketTLV::create(packet, VpnPacket::PAYLOAD_TYPE_TUNNELLED); -} - -bool TunnelledPacket::parse_as_ipv6() { - return parse_ipv6_header(get_payload(), get_payload_size(), _ipv6_header); -} diff --git a/VpnPacket.hpp b/VpnPacket.hpp index cb27d16..f341afd 100644 --- a/VpnPacket.hpp +++ b/VpnPacket.hpp @@ -14,7 +14,17 @@ * +---------------+---------------+---------------+---------------+ * | Sequence number [4B] | * +---------------------------------------------------------------+ - * | Sending timestamp (μs) [4B] | + * |C| Sending timestamp (μs) [4B-1b] | + * +---------------+-----------------------------------------------+ + * | ... | + * +---------------------------------------------------------------+ + * + * Where C is a single bit. If set, the packet is a control packet, containing + * TLVs. If unset, the packet is a tunnelled packet bearing data to be + * reinjected. + * + * If C is set, the remaining of the packet has the following structure: + * * +---------------+-----------------------------------------------+ * | Type [1B] | First payload size (B) [2B] | Payload | * +---------------+-----------------------------------------------+ @@ -27,7 +37,7 @@ * | ... | * +---------------------------------------------------------------+ * - * Where + * Where: * - Type is one of the values from PayloadType below; * - Sender ID is an arbitrary value, recommended to be randomly chosen * - Payload size is the size of the payload (excluding headers), in bytes; @@ -40,32 +50,30 @@ class VpnPacketTLV; class VpnPacket { public: static const size_t VPN_HEADER_BYTES; - static const size_t TLV_HEADER_BYTES; - - enum PayloadType { - PAYLOAD_TYPE_UNDEF, ///< Undefined packet type - PAYLOAD_TYPE_TUNNELLED, ///< A tunnelled packet - PAYLOAD_TYPE_RR, ///< Receiver report - PAYLOAD_TYPE_REMB, ///< Receiver Estimated Maximum Bitrate - }; - class PeerNotSet: public std::exception {}; - VpnPacket(size_t mtu); + VpnPacket(size_t mtu, bool inbound); ~VpnPacket(); - VpnPacketTLV first_tlv(); + // Remove copy constructor and operator= + VpnPacket(const VpnPacket& copy) = delete; + VpnPacket& operator=(const VpnPacket& copy) = delete; + + /// Move constructor + VpnPacket(VpnPacket&& move_from); + VpnPacket& operator=(VpnPacket&& move_from) = delete; /// Get the maximal payload space for a given tunnel MTU static size_t get_tunnelled_mtu(size_t udp_mtu); - /// Set packet peer -- used for sequence numbers - void set_peer(VpnPeer* peer) { _peer = peer; } + /// Set packet peer -- used for sequence numbers and loss rate + void set_peer(VpnPeer* peer); /// Get a pointer to the packet payload (const version) - const char* get_payload() const { return _data + VPN_HEADER_BYTES; } + const char* get_payload() const { + return _data.get() + VPN_HEADER_BYTES; } /// Get a pointer to the packet payload - char* get_payload() { return _data + VPN_HEADER_BYTES; } + char* get_payload() { return _data.get() + VPN_HEADER_BYTES; } /// Get a pointer to the first free byte of the packet payload char* get_next_payload() { return get_payload() + get_payload_size(); } /// Get the space allocated for the packet payload @@ -83,9 +91,9 @@ class VpnPacket { _data_size += payload_size_increment; } /// Get a pointer to the full packet data (const version) - const char* get_data() const { return _data; } + const char* get_data() const { return _data.get(); } /// Get a pointer to the full packet data - char* get_data() { return _data; } + char* get_data() { return _data.get(); } /// Get the space allocated for the packet size_t get_data_space() const { return _data_space; } /// Get the total current size of the packet @@ -99,6 +107,8 @@ class VpnPacket { uint32_t get_sending_timestamp() const; /// Get this packet's reception timestamp uint32_t get_reception_timestamp() const { return _reception_timestamp; } + /// Check whether this packet is control or data + bool is_control() const; /** Fill the headers of the packet. This method must be called as close * to the time the packet is actually sent as possible, as it handles @@ -111,30 +121,69 @@ class VpnPacket { */ void upon_reception(); + protected: + void set_control(bool is_control); + private: // methods inline uint32_t next_seqno(); private: VpnPeer* _peer; // raw pointer: we do not own the peer in any way + bool _inbound; ///< is the packet received or sent? - char* _data; + std::unique_ptr _data; size_t _data_space, _data_size; uint32_t _reception_timestamp; }; +class VpnControlPacket: public VpnPacket { + public: + static const size_t TLV_HEADER_BYTES; + + VpnControlPacket(size_t mtu, bool inbound); + VpnControlPacket(VpnPacket&& move_from); + + VpnPacketTLV first_tlv(); +}; + +/** A packet sent through the VPN tunnel. */ +class VpnDataPacket: public VpnPacket { + public: + VpnDataPacket(size_t mtu, bool inbound); + VpnDataPacket(VpnPacket&& move_from); + + static VpnDataPacket create(VpnPacket& packet); + + /// Try to parse the packet as IPv6, return `false` upon failure. + bool parse_as_ipv6(); + bool ipv6_parsed() const { return _ipv6_parsed; } + const IPv6Header& get_ipv6_header() const { return _ipv6_header; } + + private: + bool _ipv6_parsed; + IPv6Header _ipv6_header; +}; + /** Base class for a TLV contained in a VpnPacket */ class VpnPacketTLV { public: - VpnPacketTLV(VpnPacket& packet, size_t payload_offset); + VpnPacketTLV(VpnControlPacket& packet, size_t payload_offset); VpnPacketTLV(const VpnPacketTLV& other); - static VpnPacketTLV create( - VpnPacket& packet, - VpnPacket::PayloadType type=VpnPacket::PAYLOAD_TYPE_UNDEF); + enum PayloadType { + PAYLOAD_TYPE_UNDEF, ///< Undefined packet type + PAYLOAD_TYPE_RR, ///< Receiver report + PAYLOAD_TYPE_REMB, ///< Receiver Estimated Maximum Bitrate + }; - const VpnPacket& get_packet() const { return _packet; } - VpnPacket& get_packet() { return _packet; } + + static VpnPacketTLV create( + VpnControlPacket& packet, + PayloadType type=PAYLOAD_TYPE_UNDEF); + + const VpnControlPacket& get_packet() const { return _packet; } + VpnControlPacket& get_packet() { return _packet; } /// Get the next TLV in this packet. VpnPacketTLV next_tlv(); @@ -150,10 +199,12 @@ class VpnPacketTLV { /// Get a pointer to the payload (const version) const char* get_payload() const { - return _packet.get_payload() + _tlv_pos + VpnPacket::TLV_HEADER_BYTES; } + return _packet.get_payload() + _tlv_pos + + VpnControlPacket::TLV_HEADER_BYTES; } /// Get a pointer to the payload char* get_payload() { - return _packet.get_payload() + _tlv_pos + VpnPacket::TLV_HEADER_BYTES; } + return _packet.get_payload() + _tlv_pos + + VpnControlPacket::TLV_HEADER_BYTES; } /// Get the current payload size uint16_t get_payload_size() const; /// Set the current payload size @@ -168,43 +219,22 @@ class VpnPacketTLV { char* get_data() { return _packet.get_payload() + _tlv_pos; } /// Get the current raw data size uint16_t get_data_size() const { - return get_payload_size() + VpnPacket::TLV_HEADER_BYTES; } + return get_payload_size() + VpnControlPacket::TLV_HEADER_BYTES; } /// Set the current raw data size void set_data_size(uint16_t size) { - set_payload_size(size + VpnPacket::TLV_HEADER_BYTES); } + set_payload_size(size + VpnControlPacket::TLV_HEADER_BYTES); } /// Get this TLV's type - VpnPacket::PayloadType get_type() const; + PayloadType get_type() const; bool operator==(const VpnPacketTLV& other) const { return &_packet == &other._packet && _tlv_pos == other._tlv_pos; } protected: // meth /// Set this TLV's type - void set_type(VpnPacket::PayloadType type); + void set_type(PayloadType type); protected: - VpnPacket& _packet; + VpnControlPacket& _packet; size_t _tlv_pos; - - friend class TunnelledPacket; -}; - -/** A packet sent through the VPN tunnel. - * - * This must instantiated just before filling it with data. */ -class TunnelledPacket: public VpnPacketTLV { - public: - TunnelledPacket(VpnPacket& packet, size_t payload_offset); - TunnelledPacket(const VpnPacketTLV& copy); - static TunnelledPacket create(VpnPacket& packet); - - /// Try to parse the packet as IPv6, return `false` upon failure. - bool parse_as_ipv6(); - bool ipv6_parsed() const { return _ipv6_parsed; } - const IPv6Header& get_ipv6_header() const { return _ipv6_header; } - - private: - bool _ipv6_parsed; - IPv6Header _ipv6_header; }; diff --git a/VpnPeer.cpp b/VpnPeer.cpp index 68e73a7..c5068f1 100644 --- a/VpnPeer.cpp +++ b/VpnPeer.cpp @@ -29,9 +29,14 @@ size_t VpnPeer::write(const VpnPacket& packet) { return write(packet.get_data(), packet.get_data_size()); } +void VpnPeer::got_inbound_packet(const VpnPacket& packet) { + _packet_loss.log_packet(packet.get_seqno()); +} + PacketLossLogger::PacketLossLogger() : _cur_seqno(0) {} void PacketLossLogger::log_packet(uint32_t seqno) { + kdebugf(">> Logging %lu (loss %lf)\n", seqno, get_loss_rate()); uint32_t m_seqno = seqno % PACKET_LOSS_HISTSIZE; int64_t diff = (int64_t)seqno - _cur_seqno; diff --git a/VpnPeer.hpp b/VpnPeer.hpp index 7f836f3..ac1355c 100644 --- a/VpnPeer.hpp +++ b/VpnPeer.hpp @@ -56,15 +56,21 @@ class VpnPeer { void set_int_addr(const in6_addr& int_addr); + const PacketLossLogger& get_loss_logger() { return _packet_loss; } + 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++; } + void got_inbound_packet(const VpnPacket& packet); + private: UdpVpn* _vpn; sockaddr_in6 _ext_addr; in6_addr _int_addr; uint32_t _next_send_seqno; + + PacketLossLogger _packet_loss; }; diff --git a/main.cpp b/main.cpp index a6b759c..b66097f 100644 --- a/main.cpp +++ b/main.cpp @@ -27,6 +27,10 @@ void stop_sig_handler(int signal) { vpn_instance->stop(); } +void dump_sig_handler(int /*signal*/) { + vpn_instance->dump_requested(); +} + bool parse_options(int argc, char** argv, ProgOptions& opts) { int option; memset(&opts, 0, sizeof(opts)); @@ -91,6 +95,7 @@ int main(int argc, char** argv) { printf("=== END OPTIONS ==\n\n"); signal(SIGINT, stop_sig_handler); + signal(SIGUSR1, dump_sig_handler); try { if(program_options.listen && program_options.has_peer) {