2020-06-05 17:30:35 +02:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
/** A packet to be transmitted or received over the VPN socket */
|
|
|
|
|
|
|
|
#include <cstdlib>
|
2020-06-10 18:49:36 +02:00
|
|
|
#include <memory>
|
2020-06-05 17:30:35 +02:00
|
|
|
|
|
|
|
#include "ip_header.hpp"
|
|
|
|
|
2020-06-10 18:49:36 +02:00
|
|
|
/** VPN packet layout:
|
|
|
|
*
|
|
|
|
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
|
|
|
* | 1B | 1B | 1B | 1B | 1B | 1B | 1B | 1B |
|
|
|
|
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
|
|
|
* | Sequence number [4B] | Sending timestamp (μs) [4B] |
|
|
|
|
* +---------------------------------------------------------------+
|
|
|
|
* | Nested packet (payload) |
|
|
|
|
* +---------------------------------------------------------------+
|
|
|
|
*/
|
|
|
|
|
|
|
|
class VpnPeer;
|
|
|
|
|
2020-06-05 17:30:35 +02:00
|
|
|
class VpnPacket {
|
|
|
|
public:
|
2020-06-10 18:49:36 +02:00
|
|
|
static const size_t VPN_HEADER_BYTES;
|
2020-06-05 17:30:35 +02:00
|
|
|
|
|
|
|
VpnPacket(size_t mtu);
|
|
|
|
~VpnPacket();
|
|
|
|
|
2020-06-10 18:49:36 +02:00
|
|
|
/// Set packet peer -- used for sequence numbers
|
|
|
|
void set_peer(std::shared_ptr<VpnPeer> peer) { _peer = peer; }
|
|
|
|
|
2020-06-05 17:30:35 +02:00
|
|
|
/// 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; }
|
|
|
|
|
2020-06-10 18:49:36 +02:00
|
|
|
const char* get_payload() const { return _data + VPN_HEADER_BYTES; }
|
|
|
|
char* get_payload() { return _data + VPN_HEADER_BYTES; }
|
2020-06-05 17:30:35 +02:00
|
|
|
size_t get_payload_space() const {
|
2020-06-10 18:49:36 +02:00
|
|
|
return _data_space - VPN_HEADER_BYTES; }
|
2020-06-05 17:30:35 +02:00
|
|
|
size_t get_payload_size() const {
|
2020-06-10 18:49:36 +02:00
|
|
|
return _data_size - VPN_HEADER_BYTES; }
|
2020-06-05 17:30:35 +02:00
|
|
|
void set_payload_size(size_t payload_size) {
|
2020-06-10 18:49:36 +02:00
|
|
|
_data_size = payload_size + VPN_HEADER_BYTES; }
|
2020-06-05 17:30:35 +02:00
|
|
|
|
|
|
|
const char* get_data() const { return _data; }
|
|
|
|
char* get_data() { return _data; }
|
|
|
|
size_t get_data_space() const { return _data_space; }
|
|
|
|
size_t get_data_size() const { return _data_size; }
|
|
|
|
void set_data_size(size_t data_size) { _data_size = data_size; }
|
|
|
|
|
2020-06-10 18:49:36 +02:00
|
|
|
uint32_t get_seqno() const;
|
|
|
|
uint32_t get_sending_timestamp() const;
|
|
|
|
uint32_t get_reception_timestamp() const { return _reception_timestamp; }
|
|
|
|
|
|
|
|
/** 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
|
|
|
|
* timestamps. */
|
|
|
|
void prepare_for_sending();
|
|
|
|
|
|
|
|
/** Do what must be done at reception, eg. keep the reception
|
|
|
|
* timestamp. This method must be called as close to the time the
|
|
|
|
* packet is actually received as possible, as it handles timestamps.
|
|
|
|
*/
|
|
|
|
void upon_reception();
|
|
|
|
|
|
|
|
private: // methods
|
|
|
|
inline uint32_t next_seqno();
|
|
|
|
|
2020-06-05 17:30:35 +02:00
|
|
|
private:
|
2020-06-10 18:49:36 +02:00
|
|
|
std::shared_ptr<VpnPeer> _peer;
|
|
|
|
|
2020-06-05 17:30:35 +02:00
|
|
|
char* _data;
|
|
|
|
size_t _data_space, _data_size;
|
|
|
|
|
|
|
|
bool _ipv6_parsed;
|
|
|
|
IPv6Header _ipv6_header;
|
2020-06-10 18:49:36 +02:00
|
|
|
|
|
|
|
uint32_t _reception_timestamp;
|
|
|
|
|
|
|
|
static uint32_t _next_general_seqno;
|
2020-06-05 17:30:35 +02:00
|
|
|
};
|