UDPConnection/src/UDPC_Defines.hpp

300 lines
8.8 KiB
C++
Raw Normal View History

2019-08-30 05:57:24 +00:00
// vim: foldmethod=marker
2019-06-06 07:02:48 +00:00
#ifndef UDPC_DEFINES_HPP
#define UDPC_DEFINES_HPP
#define UDPC_CONTEXT_IDENTIFIER 0x902F4DB3
2019-07-25 11:51:08 +00:00
#define UDPC_SENT_PKTS_MAX_SIZE 33
#define UDPC_QUEUED_PKTS_MAX_SIZE 64
#define UDPC_RECEIVED_PKTS_MAX_SIZE 64
2019-07-25 11:51:08 +00:00
#define UDPC_ID_CONNECT 0x80000000
#define UDPC_ID_PING 0x40000000
#define UDPC_ID_NO_REC_CHK 0x20000000
#define UDPC_ID_RESENDING 0x10000000
2019-06-06 07:02:48 +00:00
#define UDPC_ATOSTR_BUFCOUNT 32
#define UDPC_ATOSTR_BUFSIZE 40
#define UDPC_ATOSTR_SIZE (UDPC_ATOSTR_BUFCOUNT * UDPC_ATOSTR_BUFSIZE)
#define UDPC_CHECK_LOG(ctx, type, ...) if(ctx->willLog(type)){ctx->log(type, __VA_ARGS__);}
2019-06-06 07:02:48 +00:00
#include <atomic>
2019-06-06 07:42:07 +00:00
#include <bitset>
2019-07-25 11:51:08 +00:00
#include <chrono>
2019-06-06 07:42:07 +00:00
#include <cstdint>
2019-07-21 05:29:31 +00:00
#include <deque>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <random>
#include <memory>
2019-08-29 03:56:09 +00:00
#include <thread>
2019-09-16 03:00:25 +00:00
#include <mutex>
2019-08-29 03:56:09 +00:00
#include <iostream>
2019-06-06 07:02:48 +00:00
#include "TSLQueue.hpp"
2020-01-09 07:57:01 +00:00
#include "UDPC.h"
2019-06-06 07:02:48 +00:00
#include <sodium.h>
#define UDPC_MIN_HEADER_SIZE 20
#define UDPC_CON_HEADER_SIZE (UDPC_MIN_HEADER_SIZE+4)
#define UDPC_CCL_HEADER_SIZE (UDPC_MIN_HEADER_SIZE+4+crypto_sign_PUBLICKEYBYTES+12)
#define UDPC_CSR_HEADER_SIZE (UDPC_MIN_HEADER_SIZE+4+crypto_sign_PUBLICKEYBYTES+crypto_sign_BYTES)
#define UDPC_LSFULL_HEADER_SIZE (UDPC_MIN_HEADER_SIZE+1+crypto_sign_BYTES)
#define UDPC_NSFULL_HEADER_SIZE (UDPC_MIN_HEADER_SIZE+1)
#define UDPC_UPDATE_MS_MIN 4
#define UDPC_UPDATE_MS_MAX 333
#define UDPC_UPDATE_MS_DEFAULT 8
2019-06-06 07:02:48 +00:00
namespace UDPC {
static const auto ONE_SECOND = std::chrono::seconds(1);
static const auto TEN_SECONDS = std::chrono::seconds(10);
static const auto THIRTY_SECONDS = std::chrono::seconds(30);
2019-07-25 11:51:08 +00:00
static const auto INIT_PKT_INTERVAL_DT = std::chrono::seconds(5);
static const auto HEARTBEAT_PKT_INTERVAL_DT = std::chrono::milliseconds(150);
static const auto PACKET_TIMEOUT_TIME = ONE_SECOND;
static const auto GOOD_RTT_LIMIT = std::chrono::milliseconds(250);
static const auto CONNECTION_TIMEOUT = TEN_SECONDS;
static const auto GOOD_MODE_SEND_RATE = std::chrono::microseconds(33333);
static const auto BAD_MODE_SEND_RATE = std::chrono::milliseconds(100);
// forward declaration
struct Context;
2019-07-25 11:51:08 +00:00
struct SentPktInfo {
typedef std::shared_ptr<SentPktInfo> Ptr;
SentPktInfo();
uint32_t id;
std::chrono::steady_clock::time_point sentTime;
};
struct ConnectionIdHasher {
std::size_t operator()(const UDPC_ConnectionId& key) const;
};
struct IPV6_Hasher {
2019-11-11 04:37:51 +00:00
std::size_t operator()(const UDPC_IPV6_ADDR_TYPE& addr) const;
};
struct PKContainer {
PKContainer();
PKContainer(const unsigned char *pk);
unsigned char pk[crypto_sign_PUBLICKEYBYTES];
std::size_t operator()(const PKContainer& container) const;
bool operator==(const PKContainer& other) const;
};
2019-07-21 05:29:31 +00:00
struct ConnectionData {
ConnectionData(bool isUsingLibsodium);
ConnectionData(
bool isServer,
Context *ctx,
UDPC_IPV6_ADDR_TYPE addr,
uint32_t scope_id,
uint16_t port,
bool isUsingLibsodium,
unsigned char *sk,
unsigned char *pk);
2019-08-22 07:08:05 +00:00
// copy
ConnectionData(const ConnectionData& other) = delete;
ConnectionData& operator=(const ConnectionData& other) = delete;
// move
ConnectionData(ConnectionData&& other) = default;
ConnectionData& operator=(ConnectionData&& other) = default;
void cleanupSentPkts();
2019-07-21 05:29:31 +00:00
/*
* 0 - trigger send
* 1 - is good mode
* 2 - is good rtt
2019-07-25 11:51:08 +00:00
* 3 - initiating connection
2019-07-21 05:29:31 +00:00
* 4 - is id set
* 5 - error initializing keys for public key encryption
* 6 - using libsodium for header verification
2019-07-21 05:29:31 +00:00
*/
std::bitset<8> flags;
2019-07-21 05:29:31 +00:00
uint32_t id;
uint32_t lseq;
uint32_t rseq;
uint32_t ack;
std::chrono::steady_clock::duration timer;
std::chrono::steady_clock::duration toggleT;
std::chrono::steady_clock::duration toggleTimer;
std::chrono::steady_clock::duration toggledTimer;
2019-11-11 04:37:51 +00:00
UDPC_IPV6_ADDR_TYPE addr; // in network order
2019-09-18 08:35:14 +00:00
uint32_t scope_id;
2019-08-22 07:08:05 +00:00
uint16_t port; // in native order
2019-07-25 11:51:08 +00:00
std::deque<UDPC_PacketInfo> sentPkts;
std::deque<UDPC_PacketInfo> sendPkts;
std::deque<UDPC_PacketInfo> priorityPkts;
// pkt id to pkt shared_ptr
std::unordered_map<uint32_t, SentPktInfo::Ptr> sentInfoMap;
2019-07-21 05:29:31 +00:00
std::chrono::steady_clock::time_point received;
std::chrono::steady_clock::time_point sent;
std::chrono::steady_clock::duration rtt;
unsigned char sk[crypto_sign_SECRETKEYBYTES];
unsigned char pk[crypto_sign_PUBLICKEYBYTES];
unsigned char peer_pk[crypto_sign_PUBLICKEYBYTES];
// client - 4 byte string size, rest is string
// server - detached signature of size crypto_sign_BYTES
std::unique_ptr<char[]> verifyMessage;
2019-07-21 05:29:31 +00:00
}; // struct ConnectionData
2019-06-06 07:02:48 +00:00
struct Context {
2019-08-29 03:56:09 +00:00
public:
2019-06-06 07:02:48 +00:00
Context(bool isThreaded);
bool willLog(UDPC_LoggingType);
2019-08-29 03:56:09 +00:00
void log(UDPC_LoggingType) {}
template<typename... Targs>
void log(UDPC_LoggingType type, Targs... args) {
log_impl(type, args...);
}
private:
void log_impl(UDPC_LoggingType) {}
template<typename... Targs>
2019-08-30 05:57:24 +00:00
void log_impl(UDPC_LoggingType type, Targs... args) { // {{{
switch(type) {
case UDPC_LoggingType::UDPC_ERROR:
std::cerr << "ERROR: ";
2019-08-29 03:56:09 +00:00
break;
case UDPC_LoggingType::UDPC_WARNING:
std::cerr << "WARN: ";
2019-08-29 03:56:09 +00:00
break;
case UDPC_LoggingType::UDPC_VERBOSE:
std::cerr << "VERB: ";
2019-08-29 03:56:09 +00:00
break;
case UDPC_LoggingType::UDPC_INFO:
std::cerr << "INFO: ";
2019-08-29 03:56:09 +00:00
break;
case UDPC_LoggingType::UDPC_DEBUG:
std::cerr << "DEBUG: ";
break;
2019-08-29 03:56:09 +00:00
default:
return;
}
log_impl_next(type, args...);
2019-08-30 05:57:24 +00:00
} // }}}
2019-08-29 03:56:09 +00:00
void log_impl_next(UDPC_LoggingType) {
std::cerr << '\n';
}
template<typename T, typename... Targs>
2019-08-30 05:57:24 +00:00
void log_impl_next(UDPC_LoggingType type, T value, Targs... args) { // {{{
std::cerr << value;
log_impl_next(type, args...);
2019-08-30 05:57:24 +00:00
} // }}}
2019-08-29 03:56:09 +00:00
public:
2019-09-16 02:40:43 +00:00
void update_impl();
2019-06-06 07:02:48 +00:00
uint_fast32_t _contextIdentifier;
2019-08-27 05:06:27 +00:00
char recvBuf[UDPC_PACKET_MAX_SIZE];
2019-06-06 07:02:48 +00:00
/*
2019-07-25 11:51:08 +00:00
* 0 - is threaded
* 1 - is client
* 2 - libsodium enabled
2019-06-06 07:02:48 +00:00
*/
std::bitset<8> flags;
2019-06-06 07:02:48 +00:00
std::atomic_bool isAcceptNewConnections;
std::atomic_bool isReceivingEvents;
2019-06-06 07:02:48 +00:00
std::atomic_uint32_t protocolID;
std::atomic_uint_fast8_t loggingType;
// See UDPC_AuthPolicy enum in UDPConnection.h for possible values
std::atomic_uint_fast8_t authPolicy;
std::atomic_uint32_t atostrBufIndex;
char atostrBuf[UDPC_ATOSTR_SIZE];
2019-07-21 05:29:31 +00:00
2019-09-19 03:23:15 +00:00
UDPC_SOCKETTYPE socketHandle;
2019-11-11 04:37:51 +00:00
UDPC_IPV6_SOCKADDR_TYPE socketInfo;
2019-07-21 05:29:31 +00:00
std::chrono::steady_clock::time_point lastUpdated;
// ipv6 address and port (as UDPC_ConnectionId) to ConnectionData
std::unordered_map<UDPC_ConnectionId, ConnectionData, ConnectionIdHasher> conMap;
// ipv6 address to all connected UDPC_ConnectionId
2019-11-11 04:37:51 +00:00
std::unordered_map<UDPC_IPV6_ADDR_TYPE, std::unordered_set<UDPC_ConnectionId, ConnectionIdHasher>, IPV6_Hasher> addrConMap;
// id to ipv6 address and port (as UDPC_ConnectionId)
std::unordered_map<uint32_t, UDPC_ConnectionId> idMap;
std::unordered_set<UDPC_ConnectionId, ConnectionIdHasher> deletionMap;
std::unordered_set<PKContainer, PKContainer> peerPKWhitelist;
std::deque<UDPC_PacketInfo> receivedPkts;
std::mutex receivedPktsMutex;
TSLQueue<UDPC_PacketInfo> cSendPkts;
// handled internally
std::deque<UDPC_Event> internalEvents;
std::mutex internalEventsMutex;
// handled via interface, if isReceivingEvents is true
std::deque<UDPC_Event> externalEvents;
std::mutex externalEventsMutex;
2019-07-25 11:51:08 +00:00
std::default_random_engine rng_engine;
2019-09-16 02:40:43 +00:00
std::thread thread;
std::atomic_bool threadRunning;
std::mutex conMapMutex;
std::mutex peerPKWhitelistMutex;
2019-09-16 02:40:43 +00:00
std::chrono::milliseconds threadedSleepTime;
unsigned char sk[crypto_sign_SECRETKEYBYTES];
unsigned char pk[crypto_sign_PUBLICKEYBYTES];
std::atomic_bool keysSet;
2019-06-06 07:02:48 +00:00
}; // struct Context
Context *verifyContext(UDPC_HContext ctx);
2019-06-06 07:02:48 +00:00
bool isBigEndian();
void be64(char *integer);
void be64_copy(char *out, const char *in);
2019-07-25 11:51:08 +00:00
/*
* flags:
* 0x1 - connect
* 0x2 - ping
* 0x4 - no_rec_chk
* 0x8 - resending
2019-07-25 11:51:08 +00:00
*/
void preparePacket(char *data, uint32_t protocolID, uint32_t conID,
uint32_t rseq, uint32_t ack, uint32_t *seqID, int flags);
2019-07-25 11:51:08 +00:00
uint32_t generateConnectionID(Context &ctx);
2019-08-29 03:56:09 +00:00
float durationToFSec(const std::chrono::steady_clock::duration& duration);
uint16_t durationToMS(const std::chrono::steady_clock::duration& duration);
2019-08-29 03:56:09 +00:00
float timePointsToFSec(
const std::chrono::steady_clock::time_point& older,
const std::chrono::steady_clock::time_point& newer);
UDPC_PacketInfo get_empty_pinfo();
2019-09-16 02:40:43 +00:00
void threadedUpdate(Context *ctx);
2019-06-06 07:02:48 +00:00
} // namespace UDPC
bool operator ==(const UDPC_ConnectionId& a, const UDPC_ConnectionId& b);
2019-11-11 04:37:51 +00:00
bool operator ==(const UDPC_IPV6_ADDR_TYPE& a, const UDPC_IPV6_ADDR_TYPE& b);
2019-06-06 07:02:48 +00:00
#endif