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
|
2019-08-18 10:14:14 +00:00
|
|
|
#define UDPC_QUEUED_PKTS_MAX_SIZE 32
|
2019-08-27 04:06:15 +00:00
|
|
|
#define UDPC_RECEIVED_PKTS_MAX_SIZE 50
|
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
|
|
|
|
2019-09-07 07:36:11 +00:00
|
|
|
#define UDPC_ATOSTR_BUFCOUNT 32
|
|
|
|
#define UDPC_ATOSTR_BUFSIZE 40
|
2019-09-03 07:19:47 +00:00
|
|
|
#define UDPC_ATOSTR_SIZE (UDPC_ATOSTR_BUFCOUNT * UDPC_ATOSTR_BUFSIZE)
|
|
|
|
|
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>
|
2019-08-28 07:38:14 +00:00
|
|
|
#include <unordered_set>
|
2019-08-22 11:16:07 +00:00
|
|
|
#include <queue>
|
2019-08-18 10:14:14 +00:00
|
|
|
#include <random>
|
2019-08-22 11:16:07 +00:00
|
|
|
#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
|
|
|
|
2019-07-21 05:29:31 +00:00
|
|
|
#include "TSQueue.hpp"
|
2019-07-25 11:51:08 +00:00
|
|
|
#include "UDPConnection.h"
|
2019-06-06 07:02:48 +00:00
|
|
|
|
|
|
|
namespace UDPC {
|
|
|
|
|
2019-08-27 07:31:24 +00:00
|
|
|
static const auto ONE_SECOND = std::chrono::seconds(1);
|
|
|
|
static const auto TEN_SECONDS = std::chrono::seconds(10);
|
2019-08-29 02:07:24 +00:00
|
|
|
static const auto THIRTY_SECONDS = std::chrono::seconds(30);
|
2019-08-27 07:31:24 +00:00
|
|
|
|
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);
|
2019-08-27 07:31:24 +00:00
|
|
|
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);
|
2019-08-18 10:14:14 +00:00
|
|
|
|
2019-08-22 11:16:07 +00:00
|
|
|
// forward declaration
|
2019-08-18 10:14:14 +00:00
|
|
|
struct Context;
|
2019-07-25 11:51:08 +00:00
|
|
|
|
2019-08-22 11:16:07 +00:00
|
|
|
struct SentPktInfo {
|
|
|
|
typedef std::shared_ptr<SentPktInfo> Ptr;
|
|
|
|
|
|
|
|
SentPktInfo();
|
|
|
|
|
|
|
|
uint32_t id;
|
|
|
|
std::chrono::steady_clock::time_point sentTime;
|
|
|
|
};
|
|
|
|
|
2019-09-03 03:06:46 +00:00
|
|
|
struct ConnectionIdHasher {
|
|
|
|
std::size_t operator()(const UDPC_ConnectionId& key) const;
|
2019-08-27 08:00:29 +00:00
|
|
|
};
|
|
|
|
|
2019-09-07 07:36:11 +00:00
|
|
|
struct IPV6_Hasher {
|
|
|
|
std::size_t operator()(const struct in6_addr& addr) const;
|
|
|
|
};
|
|
|
|
|
2019-07-21 05:29:31 +00:00
|
|
|
struct ConnectionData {
|
2019-08-18 10:14:14 +00:00
|
|
|
ConnectionData();
|
2019-09-18 08:35:14 +00:00
|
|
|
ConnectionData(bool isServer, Context *ctx, struct in6_addr addr, uint32_t scope_id, uint16_t port);
|
2019-08-18 10:14:14 +00:00
|
|
|
|
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;
|
|
|
|
|
2019-08-22 11:16:07 +00:00
|
|
|
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
|
|
|
|
*/
|
|
|
|
std::bitset<32> flags;
|
|
|
|
uint32_t id;
|
|
|
|
uint32_t lseq;
|
|
|
|
uint32_t rseq;
|
|
|
|
uint32_t ack;
|
2019-08-27 07:31:24 +00:00
|
|
|
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-09-07 07:36:11 +00:00
|
|
|
struct in6_addr 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;
|
|
|
|
TSQueue<UDPC_PacketInfo> sendPkts;
|
|
|
|
TSQueue<UDPC_PacketInfo> priorityPkts;
|
2019-08-27 04:03:38 +00:00
|
|
|
TSQueue<UDPC_PacketInfo> receivedPkts;
|
2019-08-22 11:16:07 +00:00
|
|
|
// 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;
|
2019-08-27 07:31:24 +00:00
|
|
|
std::chrono::steady_clock::duration rtt;
|
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);
|
|
|
|
|
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) { // {{{
|
2019-08-29 03:56:09 +00:00
|
|
|
switch(loggingType.load()) {
|
2019-09-19 01:58:19 +00:00
|
|
|
case UDPC_LoggingType::UDPC_SILENT:
|
2019-08-29 03:56:09 +00:00
|
|
|
return;
|
2019-09-19 01:58:19 +00:00
|
|
|
case UDPC_LoggingType::UDPC_ERROR:
|
|
|
|
if(type == UDPC_LoggingType::UDPC_ERROR) {
|
2019-08-29 03:56:09 +00:00
|
|
|
std::cerr << "ERROR: ";
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
2019-09-19 01:58:19 +00:00
|
|
|
case UDPC_LoggingType::UDPC_WARNING:
|
2019-08-29 03:56:09 +00:00
|
|
|
switch(type) {
|
2019-09-19 01:58:19 +00:00
|
|
|
case UDPC_LoggingType::UDPC_ERROR:
|
2019-08-29 03:56:09 +00:00
|
|
|
std::cerr << "ERROR: ";
|
|
|
|
break;
|
2019-09-19 01:58:19 +00:00
|
|
|
case UDPC_LoggingType::UDPC_WARNING:
|
2019-08-29 03:56:09 +00:00
|
|
|
std::cerr << "WARNING: ";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
2019-09-19 01:58:19 +00:00
|
|
|
case UDPC_LoggingType::UDPC_VERBOSE:
|
2019-08-29 03:56:09 +00:00
|
|
|
switch(type) {
|
2019-09-19 01:58:19 +00:00
|
|
|
case UDPC_LoggingType::UDPC_ERROR:
|
2019-08-29 03:56:09 +00:00
|
|
|
std::cerr << "ERROR: ";
|
|
|
|
break;
|
2019-09-19 01:58:19 +00:00
|
|
|
case UDPC_LoggingType::UDPC_WARNING:
|
2019-08-29 03:56:09 +00:00
|
|
|
std::cerr << "WARNING: ";
|
|
|
|
break;
|
2019-09-19 01:58:19 +00:00
|
|
|
case UDPC_LoggingType::UDPC_VERBOSE:
|
2019-08-29 03:56:09 +00:00
|
|
|
std::cerr << "VERBOSE: ";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
2019-09-19 01:58:19 +00:00
|
|
|
case UDPC_LoggingType::UDPC_INFO:
|
2019-08-29 03:56:09 +00:00
|
|
|
switch(type) {
|
2019-09-19 01:58:19 +00:00
|
|
|
case UDPC_LoggingType::UDPC_ERROR:
|
2019-08-29 03:56:09 +00:00
|
|
|
std::cerr << "ERROR: ";
|
|
|
|
break;
|
2019-09-19 01:58:19 +00:00
|
|
|
case UDPC_LoggingType::UDPC_WARNING:
|
2019-08-29 03:56:09 +00:00
|
|
|
std::cerr << "WARNING: ";
|
|
|
|
break;
|
2019-09-19 01:58:19 +00:00
|
|
|
case UDPC_LoggingType::UDPC_VERBOSE:
|
2019-08-29 03:56:09 +00:00
|
|
|
std::cerr << "VERBOSE: ";
|
|
|
|
break;
|
2019-09-19 01:58:19 +00:00
|
|
|
case UDPC_LoggingType::UDPC_INFO:
|
2019-08-29 03:56:09 +00:00
|
|
|
std::cerr << "INFO: ";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
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) { // {{{
|
2019-08-29 03:56:09 +00:00
|
|
|
switch(loggingType.load()) {
|
2019-09-19 01:58:19 +00:00
|
|
|
case UDPC_LoggingType::UDPC_SILENT:
|
2019-08-29 03:56:09 +00:00
|
|
|
return;
|
2019-09-19 01:58:19 +00:00
|
|
|
case UDPC_LoggingType::UDPC_ERROR:
|
|
|
|
if(type == UDPC_LoggingType::UDPC_ERROR) {
|
2019-08-29 03:56:09 +00:00
|
|
|
std::cerr << value;
|
|
|
|
}
|
|
|
|
break;
|
2019-09-19 01:58:19 +00:00
|
|
|
case UDPC_LoggingType::UDPC_WARNING:
|
|
|
|
if(type == UDPC_LoggingType::UDPC_ERROR || type == UDPC_LoggingType::UDPC_WARNING) {
|
2019-08-29 03:56:09 +00:00
|
|
|
std::cerr << value;
|
|
|
|
}
|
|
|
|
break;
|
2019-09-19 01:58:19 +00:00
|
|
|
case UDPC_LoggingType::UDPC_VERBOSE:
|
|
|
|
if(type == UDPC_LoggingType::UDPC_ERROR || type == UDPC_LoggingType::UDPC_WARNING
|
|
|
|
|| type == UDPC_LoggingType::UDPC_VERBOSE) {
|
2019-08-29 03:56:09 +00:00
|
|
|
std::cerr << value;
|
|
|
|
}
|
|
|
|
break;
|
2019-09-19 01:58:19 +00:00
|
|
|
case UDPC_LoggingType::UDPC_INFO:
|
|
|
|
if(type == UDPC_LoggingType::UDPC_ERROR || type == UDPC_LoggingType::UDPC_WARNING
|
|
|
|
|| type == UDPC_LoggingType::UDPC_VERBOSE
|
|
|
|
|| type == UDPC_LoggingType::UDPC_INFO) {
|
2019-08-29 03:56:09 +00:00
|
|
|
std::cerr << value;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2019-08-30 03:03:26 +00:00
|
|
|
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
|
|
|
|
2019-08-18 10:14:14 +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
|
2019-08-18 10:14:14 +00:00
|
|
|
* 2 - is accepting new connections
|
2019-06-06 07:02:48 +00:00
|
|
|
*/
|
|
|
|
std::bitset<32> flags;
|
|
|
|
std::atomic_bool isAcceptNewConnections;
|
|
|
|
std::atomic_uint32_t protocolID;
|
|
|
|
std::atomic_uint_fast8_t loggingType;
|
2019-09-03 07:19:47 +00:00
|
|
|
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-09-07 07:36:11 +00:00
|
|
|
struct sockaddr_in6 socketInfo;
|
2019-07-21 05:29:31 +00:00
|
|
|
|
|
|
|
std::chrono::steady_clock::time_point lastUpdated;
|
2019-09-07 07:36:11 +00:00
|
|
|
// ipv6 address and port (as UDPC_ConnectionId) to ConnectionData
|
2019-09-03 03:06:46 +00:00
|
|
|
std::unordered_map<UDPC_ConnectionId, ConnectionData, ConnectionIdHasher> conMap;
|
2019-09-07 07:36:11 +00:00
|
|
|
// ipv6 address to all connected UDPC_ConnectionId
|
|
|
|
std::unordered_map<struct in6_addr, std::unordered_set<UDPC_ConnectionId, ConnectionIdHasher>, IPV6_Hasher> addrConMap;
|
|
|
|
// id to ipv6 address and port (as UDPC_ConnectionId)
|
2019-09-03 03:06:46 +00:00
|
|
|
std::unordered_map<uint32_t, UDPC_ConnectionId> idMap;
|
2019-07-25 11:51:08 +00:00
|
|
|
|
2019-08-18 10:14:14 +00:00
|
|
|
std::default_random_engine rng_engine;
|
|
|
|
|
2019-09-16 02:40:43 +00:00
|
|
|
std::thread thread;
|
|
|
|
std::atomic_bool threadRunning;
|
2019-09-16 03:00:25 +00:00
|
|
|
std::mutex mutex;
|
2019-09-16 02:40:43 +00:00
|
|
|
|
2019-06-06 07:02:48 +00:00
|
|
|
}; // struct Context
|
|
|
|
|
2019-08-30 03:03:26 +00:00
|
|
|
Context *verifyContext(UDPC_HContext ctx);
|
2019-06-06 07:02:48 +00:00
|
|
|
|
2019-07-07 05:44:37 +00:00
|
|
|
bool isBigEndian();
|
|
|
|
|
2019-07-25 11:51:08 +00:00
|
|
|
/*
|
|
|
|
* flags:
|
|
|
|
* - 0x1 - connect
|
|
|
|
* - 0x2 - ping
|
|
|
|
* - 0x4 - no_rec_chk
|
|
|
|
* - 0x8 - resending
|
|
|
|
*/
|
|
|
|
void preparePacket(char *data, uint32_t protocolID, uint32_t conID,
|
|
|
|
uint32_t rseq, uint32_t ack, uint32_t *seqID, int flags);
|
|
|
|
|
2019-08-18 10:14:14 +00:00
|
|
|
uint32_t generateConnectionID(Context &ctx);
|
|
|
|
|
2019-08-29 03:56:09 +00:00
|
|
|
float durationToFSec(const std::chrono::steady_clock::duration& duration);
|
|
|
|
|
|
|
|
float timePointsToFSec(
|
2019-08-22 11:16:07 +00:00
|
|
|
const std::chrono::steady_clock::time_point& older,
|
|
|
|
const std::chrono::steady_clock::time_point& newer);
|
|
|
|
|
2019-09-07 07:36:11 +00:00
|
|
|
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
|
|
|
|
|
2019-09-03 03:06:46 +00:00
|
|
|
bool operator ==(const UDPC_ConnectionId& a, const UDPC_ConnectionId& b);
|
|
|
|
|
2019-09-07 07:36:11 +00:00
|
|
|
bool operator ==(const struct in6_addr& a, const struct in6_addr& b);
|
|
|
|
|
2019-06-06 07:02:48 +00:00
|
|
|
#endif
|