2019-06-06 07:02:48 +00:00
|
|
|
#include "UDPC_Defines.hpp"
|
2019-06-06 07:42:07 +00:00
|
|
|
#include "UDPConnection.h"
|
2019-06-06 07:02:48 +00:00
|
|
|
|
2019-07-25 11:51:08 +00:00
|
|
|
#include <cassert>
|
2019-07-21 05:29:31 +00:00
|
|
|
#include <chrono>
|
2019-07-25 11:51:08 +00:00
|
|
|
#include <cstring>
|
2019-07-07 05:44:37 +00:00
|
|
|
#include <optional>
|
2019-07-21 05:29:31 +00:00
|
|
|
#include <vector>
|
2019-08-27 08:00:29 +00:00
|
|
|
#include <functional>
|
2019-08-29 03:56:09 +00:00
|
|
|
#include <type_traits>
|
2019-09-07 07:36:11 +00:00
|
|
|
#include <string>
|
|
|
|
#include <sstream>
|
|
|
|
#include <ios>
|
2019-09-18 09:39:35 +00:00
|
|
|
#include <iomanip>
|
2019-09-17 08:17:16 +00:00
|
|
|
#include <regex>
|
2019-09-20 05:01:26 +00:00
|
|
|
#include <cstdlib>
|
2019-11-18 08:37:03 +00:00
|
|
|
#include <ctime>
|
|
|
|
#include <iomanip>
|
2019-09-19 01:35:22 +00:00
|
|
|
|
|
|
|
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
|
|
|
|
#include <netioapi.h>
|
2019-09-19 03:23:15 +00:00
|
|
|
|
|
|
|
static const UDPC_IPV6_ADDR_TYPE in6addr_any = UDPC_IPV6_ADDR_TYPE{{
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0
|
|
|
|
}};
|
|
|
|
static const UDPC_IPV6_ADDR_TYPE in6addr_loopback = UDPC_IPV6_ADDR_TYPE{{
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 1
|
|
|
|
}};
|
|
|
|
|
|
|
|
typedef int socklen_t;
|
2019-09-19 01:35:22 +00:00
|
|
|
#elif UDPC_PLATFORM == UDPC_PLATFORM_MAC || UDPC_PLATFORM == UDPC_PLATFORM_LINUX
|
2019-09-18 08:35:14 +00:00
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <net/if.h>
|
2019-09-19 01:35:22 +00:00
|
|
|
#endif
|
2019-09-17 08:17:16 +00:00
|
|
|
|
2019-09-18 08:35:14 +00:00
|
|
|
//static const std::regex ipv6_regex = std::regex(R"d((([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])))d");
|
|
|
|
static const std::regex ipv6_regex_nolink = std::regex(R"d((([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])))d");
|
2019-09-19 05:30:10 +00:00
|
|
|
static const std::regex ipv6_regex_linkonly = std::regex(R"d(fe80:(:[0-9a-fA-F]{0,4}){0,4}%([0-9a-zA-Z]+))d");
|
2019-09-18 08:35:14 +00:00
|
|
|
static const std::regex ipv4_regex = std::regex(R"d((1[0-9][0-9]|2[0-4][0-9]|25[0-5]|[1-9][0-9]|[0-9])\.(1[0-9][0-9]|2[0-4][0-9]|25[0-5]|[1-9][0-9]|[0-9])\.(1[0-9][0-9]|2[0-4][0-9]|25[0-5]|[1-9][0-9]|[0-9])\.(1[0-9][0-9]|2[0-4][0-9]|25[0-5]|[1-9][0-9]|[0-9]))d");
|
2019-09-19 05:30:10 +00:00
|
|
|
static const std::regex regex_numeric = std::regex("[0-9]+");
|
2019-07-07 05:44:37 +00:00
|
|
|
|
2019-08-22 11:16:07 +00:00
|
|
|
UDPC::SentPktInfo::SentPktInfo() :
|
|
|
|
id(0),
|
|
|
|
sentTime(std::chrono::steady_clock::now())
|
|
|
|
{}
|
|
|
|
|
2019-09-03 03:06:46 +00:00
|
|
|
std::size_t UDPC::ConnectionIdHasher::operator()(const UDPC_ConnectionId& key) const {
|
2019-09-19 03:23:15 +00:00
|
|
|
std::string value((const char*)UDPC_IPV6_ADDR_SUB(key.addr), 16);
|
2019-09-18 08:35:14 +00:00
|
|
|
value.push_back((char)((key.scope_id >> 24) & 0xFF));
|
|
|
|
value.push_back((char)((key.scope_id >> 16) & 0xFF));
|
|
|
|
value.push_back((char)((key.scope_id >> 8) & 0xFF));
|
|
|
|
value.push_back((char)(key.scope_id & 0xFF));
|
2019-09-07 07:36:11 +00:00
|
|
|
value.push_back((char)((key.port >> 8) & 0xFF));
|
|
|
|
value.push_back((char)(key.port & 0xFF));
|
|
|
|
return std::hash<std::string>()(value);
|
|
|
|
}
|
|
|
|
|
2019-09-19 03:23:15 +00:00
|
|
|
std::size_t UDPC::IPV6_Hasher::operator()(const UDPC_IPV6_ADDR_TYPE& addr) const {
|
|
|
|
return std::hash<std::string>()(std::string((const char*)UDPC_IPV6_ADDR_SUB(addr), 16));
|
2019-08-27 08:00:29 +00:00
|
|
|
}
|
|
|
|
|
2019-09-03 03:06:46 +00:00
|
|
|
bool operator ==(const UDPC_ConnectionId& a, const UDPC_ConnectionId& b) {
|
2019-09-18 08:35:14 +00:00
|
|
|
return a.addr == b.addr && a.scope_id == b.scope_id && a.port == b.port;
|
2019-08-27 08:00:29 +00:00
|
|
|
}
|
|
|
|
|
2019-09-19 03:23:15 +00:00
|
|
|
bool operator ==(const UDPC_IPV6_ADDR_TYPE& a, const UDPC_IPV6_ADDR_TYPE& b) {
|
2019-09-07 07:36:11 +00:00
|
|
|
for(unsigned int i = 0; i < 16; ++i) {
|
2019-09-19 03:23:15 +00:00
|
|
|
if(UDPC_IPV6_ADDR_SUB(a)[i] != UDPC_IPV6_ADDR_SUB(b)[i]) {
|
2019-09-07 07:36:11 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-11-18 08:37:03 +00:00
|
|
|
UDPC::ConnectionData::ConnectionData(bool isUsingLibsodium) :
|
2019-08-18 10:14:14 +00:00
|
|
|
flags(),
|
2019-08-29 02:07:24 +00:00
|
|
|
id(0),
|
|
|
|
lseq(0),
|
|
|
|
rseq(0),
|
|
|
|
ack(0xFFFFFFFF),
|
2019-08-27 07:31:24 +00:00
|
|
|
timer(std::chrono::steady_clock::duration::zero()),
|
2019-08-29 02:07:24 +00:00
|
|
|
toggleT(UDPC::THIRTY_SECONDS),
|
2019-08-27 07:31:24 +00:00
|
|
|
toggleTimer(std::chrono::steady_clock::duration::zero()),
|
|
|
|
toggledTimer(std::chrono::steady_clock::duration::zero()),
|
2019-09-17 11:33:47 +00:00
|
|
|
addr({0}),
|
|
|
|
port(0),
|
2019-08-18 10:14:14 +00:00
|
|
|
sentPkts(),
|
2019-09-27 11:19:48 +00:00
|
|
|
sendPkts(),
|
|
|
|
priorityPkts(),
|
2019-08-18 10:14:14 +00:00
|
|
|
received(std::chrono::steady_clock::now()),
|
2019-08-22 07:08:05 +00:00
|
|
|
sent(std::chrono::steady_clock::now()),
|
2019-08-27 07:31:24 +00:00
|
|
|
rtt(std::chrono::steady_clock::duration::zero())
|
2019-08-18 10:14:14 +00:00
|
|
|
{
|
2019-08-27 04:06:15 +00:00
|
|
|
flags.set(0);
|
2019-09-17 11:33:47 +00:00
|
|
|
flags.reset(1);
|
2019-09-23 11:11:12 +00:00
|
|
|
|
2019-11-18 08:37:03 +00:00
|
|
|
#ifdef UDPC_LIBSODIUM_ENABLED
|
|
|
|
if(isUsingLibsodium) {
|
|
|
|
if(sodium_init() >= 0) {
|
|
|
|
crypto_sign_keypair(pk, sk);
|
|
|
|
flags.reset(5);
|
|
|
|
flags.set(6);
|
|
|
|
} else {
|
|
|
|
flags.set(5);
|
|
|
|
flags.reset(6);
|
|
|
|
}
|
2019-09-23 11:11:12 +00:00
|
|
|
} else {
|
2019-11-18 08:37:03 +00:00
|
|
|
flags.reset(5);
|
|
|
|
flags.reset(6);
|
2019-09-23 11:11:12 +00:00
|
|
|
}
|
2019-11-18 08:37:03 +00:00
|
|
|
#else
|
|
|
|
flags.reset(5);
|
|
|
|
flags.reset(6);
|
|
|
|
#endif
|
2019-08-18 10:14:14 +00:00
|
|
|
}
|
|
|
|
|
2019-09-18 08:35:14 +00:00
|
|
|
UDPC::ConnectionData::ConnectionData(
|
|
|
|
bool isServer,
|
|
|
|
Context *ctx,
|
2019-09-19 03:23:15 +00:00
|
|
|
UDPC_IPV6_ADDR_TYPE addr,
|
2019-09-18 08:35:14 +00:00
|
|
|
uint32_t scope_id,
|
2019-11-18 08:37:03 +00:00
|
|
|
uint16_t port,
|
2019-11-19 11:55:20 +00:00
|
|
|
bool isUsingLibsodium,
|
|
|
|
unsigned char *sk,
|
|
|
|
unsigned char *pk) :
|
2019-09-17 11:33:47 +00:00
|
|
|
flags(),
|
|
|
|
id(0),
|
|
|
|
lseq(0),
|
|
|
|
rseq(0),
|
|
|
|
ack(0xFFFFFFFF),
|
|
|
|
timer(std::chrono::steady_clock::duration::zero()),
|
|
|
|
toggleT(UDPC::THIRTY_SECONDS),
|
|
|
|
toggleTimer(std::chrono::steady_clock::duration::zero()),
|
|
|
|
toggledTimer(std::chrono::steady_clock::duration::zero()),
|
|
|
|
addr(addr),
|
2019-09-18 08:35:14 +00:00
|
|
|
scope_id(scope_id),
|
2019-09-17 11:33:47 +00:00
|
|
|
port(port),
|
|
|
|
sentPkts(),
|
2019-09-27 11:19:48 +00:00
|
|
|
sendPkts(),
|
|
|
|
priorityPkts(),
|
2019-09-17 11:33:47 +00:00
|
|
|
received(std::chrono::steady_clock::now()),
|
|
|
|
sent(std::chrono::steady_clock::now()),
|
|
|
|
rtt(std::chrono::steady_clock::duration::zero())
|
2019-08-18 10:14:14 +00:00
|
|
|
{
|
2019-08-29 02:07:24 +00:00
|
|
|
flags.set(3);
|
2019-08-18 10:14:14 +00:00
|
|
|
if(isServer) {
|
|
|
|
id = UDPC::generateConnectionID(*ctx);
|
|
|
|
flags.set(4);
|
2019-08-29 02:07:24 +00:00
|
|
|
} else {
|
|
|
|
lseq = 1;
|
2019-08-18 10:14:14 +00:00
|
|
|
}
|
2019-09-23 11:11:12 +00:00
|
|
|
|
2019-11-18 08:37:03 +00:00
|
|
|
#ifdef UDPC_LIBSODIUM_ENABLED
|
|
|
|
if(isUsingLibsodium) {
|
|
|
|
if(sodium_init() >= 0) {
|
2019-11-19 11:55:20 +00:00
|
|
|
if(sk && pk) {
|
|
|
|
std::memcpy(this->sk, sk, crypto_sign_SECRETKEYBYTES);
|
|
|
|
std::memcpy(this->pk, pk, crypto_sign_PUBLICKEYBYTES);
|
|
|
|
} else {
|
2019-11-21 06:15:05 +00:00
|
|
|
crypto_sign_keypair(this->pk, this->sk);
|
2019-11-19 11:55:20 +00:00
|
|
|
}
|
2019-11-18 08:37:03 +00:00
|
|
|
flags.reset(5);
|
|
|
|
flags.set(6);
|
|
|
|
} else {
|
|
|
|
flags.set(5);
|
|
|
|
flags.reset(6);
|
|
|
|
}
|
2019-09-23 11:11:12 +00:00
|
|
|
} else {
|
2019-11-18 08:37:03 +00:00
|
|
|
flags.reset(5);
|
|
|
|
flags.reset(6);
|
2019-09-23 11:11:12 +00:00
|
|
|
}
|
2019-11-18 08:37:03 +00:00
|
|
|
#else
|
|
|
|
flags.reset(5);
|
|
|
|
flags.reset(6);
|
|
|
|
#endif
|
2019-08-18 10:14:14 +00:00
|
|
|
}
|
|
|
|
|
2019-08-22 11:16:07 +00:00
|
|
|
void UDPC::ConnectionData::cleanupSentPkts() {
|
|
|
|
uint32_t id;
|
|
|
|
while(sentPkts.size() > UDPC_SENT_PKTS_MAX_SIZE) {
|
2019-09-17 11:33:47 +00:00
|
|
|
id = ntohl(*((uint32_t*)(sentPkts.front().data + 8)));
|
2019-08-28 06:54:18 +00:00
|
|
|
auto iter = sentInfoMap.find(id);
|
|
|
|
assert(iter != sentInfoMap.end()
|
|
|
|
&& "Sent packet must have correspoding entry in sentInfoMap");
|
|
|
|
sentInfoMap.erase(iter);
|
2019-08-22 11:16:07 +00:00
|
|
|
sentPkts.pop_front();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-29 02:20:36 +00:00
|
|
|
UDPC::Context::Context(bool isThreaded) :
|
|
|
|
_contextIdentifier(UDPC_CONTEXT_IDENTIFIER),
|
|
|
|
flags(),
|
|
|
|
isAcceptNewConnections(true),
|
2019-11-11 07:08:51 +00:00
|
|
|
isReceivingEvents(false),
|
2019-08-29 02:20:36 +00:00
|
|
|
protocolID(UDPC_DEFAULT_PROTOCOL_ID),
|
2019-06-06 07:02:48 +00:00
|
|
|
#ifndef NDEBUG
|
2019-11-06 05:35:16 +00:00
|
|
|
loggingType(UDPC_DEBUG),
|
2019-06-06 07:02:48 +00:00
|
|
|
#else
|
2019-09-19 01:58:19 +00:00
|
|
|
loggingType(UDPC_WARNING),
|
2019-06-06 07:02:48 +00:00
|
|
|
#endif
|
2019-09-03 07:19:47 +00:00
|
|
|
atostrBufIndex(0),
|
2019-11-06 05:35:16 +00:00
|
|
|
receivedPkts(),
|
|
|
|
cSendPkts(),
|
2019-09-16 03:00:25 +00:00
|
|
|
rng_engine(),
|
|
|
|
mutex()
|
2019-06-06 07:02:48 +00:00
|
|
|
{
|
2019-09-20 05:01:26 +00:00
|
|
|
for(unsigned int i = 0; i < UDPC_ATOSTR_SIZE; ++i) {
|
|
|
|
atostrBuf[i] = 0;
|
|
|
|
}
|
|
|
|
|
2019-07-21 04:45:42 +00:00
|
|
|
if(isThreaded) {
|
2019-06-06 07:02:48 +00:00
|
|
|
flags.set(0);
|
|
|
|
} else {
|
|
|
|
flags.reset(0);
|
|
|
|
}
|
2019-07-25 11:51:08 +00:00
|
|
|
|
2019-08-18 10:14:14 +00:00
|
|
|
rng_engine.seed(std::chrono::system_clock::now().time_since_epoch().count());
|
2019-09-07 07:36:11 +00:00
|
|
|
|
2019-09-16 02:40:43 +00:00
|
|
|
threadRunning.store(true);
|
2019-11-19 11:55:20 +00:00
|
|
|
keysSet.store(false);
|
2019-09-07 07:36:11 +00:00
|
|
|
}
|
|
|
|
|
2019-09-20 05:26:59 +00:00
|
|
|
bool UDPC::Context::willLog(UDPC_LoggingType type) {
|
|
|
|
switch(loggingType.load()) {
|
|
|
|
case UDPC_LoggingType::UDPC_SILENT:
|
|
|
|
return false;
|
|
|
|
case UDPC_LoggingType::UDPC_ERROR:
|
|
|
|
return type == UDPC_LoggingType::UDPC_ERROR;
|
|
|
|
case UDPC_LoggingType::UDPC_WARNING:
|
|
|
|
return type == UDPC_LoggingType::UDPC_ERROR
|
|
|
|
|| type == UDPC_LoggingType::UDPC_WARNING;
|
2019-11-06 05:35:16 +00:00
|
|
|
case UDPC_LoggingType::UDPC_INFO:
|
|
|
|
return type == UDPC_LoggingType::UDPC_ERROR
|
|
|
|
|| type == UDPC_LoggingType::UDPC_WARNING
|
|
|
|
|| type == UDPC_LoggingType::UDPC_INFO;
|
2019-09-20 05:26:59 +00:00
|
|
|
case UDPC_LoggingType::UDPC_VERBOSE:
|
|
|
|
return type == UDPC_LoggingType::UDPC_ERROR
|
|
|
|
|| type == UDPC_LoggingType::UDPC_WARNING
|
2019-11-06 05:35:16 +00:00
|
|
|
|| type == UDPC_LoggingType::UDPC_INFO
|
2019-09-20 05:26:59 +00:00
|
|
|
|| type == UDPC_LoggingType::UDPC_VERBOSE;
|
2019-11-06 05:35:16 +00:00
|
|
|
case UDPC_LoggingType::UDPC_DEBUG:
|
|
|
|
return type == UDPC_LoggingType::UDPC_ERROR
|
|
|
|
|| type == UDPC_LoggingType::UDPC_WARNING
|
|
|
|
|| type == UDPC_LoggingType::UDPC_INFO
|
|
|
|
|| type == UDPC_LoggingType::UDPC_VERBOSE
|
|
|
|
|| type == UDPC_LoggingType::UDPC_DEBUG;
|
2019-09-20 05:26:59 +00:00
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-16 02:40:43 +00:00
|
|
|
void UDPC::Context::update_impl() {
|
2019-07-21 05:29:31 +00:00
|
|
|
const auto now = std::chrono::steady_clock::now();
|
2019-09-18 02:42:16 +00:00
|
|
|
std::chrono::steady_clock::duration dt = now - lastUpdated;
|
|
|
|
std::chrono::steady_clock::duration temp_dt_fs;
|
2019-09-16 02:40:43 +00:00
|
|
|
lastUpdated = now;
|
2019-07-21 05:29:31 +00:00
|
|
|
|
2019-11-11 07:08:51 +00:00
|
|
|
// handle internalEvents
|
|
|
|
do {
|
|
|
|
auto optE = internalEvents.top_and_pop();
|
2019-12-17 10:12:54 +00:00
|
|
|
if(optE) {
|
|
|
|
switch(optE->type) {
|
2019-11-11 07:08:51 +00:00
|
|
|
case UDPC_ET_REQUEST_CONNECT:
|
|
|
|
{
|
2019-11-19 11:55:20 +00:00
|
|
|
unsigned char *sk = nullptr;
|
|
|
|
unsigned char *pk = nullptr;
|
|
|
|
if(keysSet.load()) {
|
|
|
|
sk = this->sk;
|
|
|
|
pk = this->pk;
|
|
|
|
}
|
2019-11-11 07:08:51 +00:00
|
|
|
UDPC::ConnectionData newCon(
|
|
|
|
false,
|
|
|
|
this,
|
2019-12-17 10:12:54 +00:00
|
|
|
optE->conId.addr,
|
|
|
|
optE->conId.scope_id,
|
|
|
|
optE->conId.port,
|
2019-11-18 08:37:03 +00:00
|
|
|
#ifdef UDPC_LIBSODIUM_ENABLED
|
2019-12-17 10:12:54 +00:00
|
|
|
flags.test(2) && optE->v.enableLibSodium != 0,
|
2019-11-19 11:55:20 +00:00
|
|
|
sk, pk);
|
2019-11-18 08:37:03 +00:00
|
|
|
#else
|
2019-11-19 11:55:20 +00:00
|
|
|
false,
|
|
|
|
sk, pk);
|
2019-11-18 08:37:03 +00:00
|
|
|
#endif
|
2019-11-11 07:08:51 +00:00
|
|
|
if(newCon.flags.test(5)) {
|
|
|
|
UDPC_CHECK_LOG(this,
|
|
|
|
UDPC_LoggingType::UDPC_ERROR,
|
|
|
|
"Failed to init ConnectionData instance (libsodium "
|
|
|
|
"init fail) while client establishing connection with ",
|
2019-12-17 10:12:54 +00:00
|
|
|
UDPC_atostr((UDPC_HContext)this, optE->conId.addr),
|
2019-11-11 07:08:51 +00:00
|
|
|
" port ",
|
2019-12-17 10:12:54 +00:00
|
|
|
optE->conId.port);
|
2019-11-11 07:08:51 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
newCon.sent = std::chrono::steady_clock::now() - UDPC::INIT_PKT_INTERVAL_DT;
|
2019-11-18 08:37:03 +00:00
|
|
|
if(flags.test(2) && newCon.flags.test(6)) {
|
2019-11-19 11:55:20 +00:00
|
|
|
// set up verification string to send to server
|
2019-11-18 08:37:03 +00:00
|
|
|
std::stringstream ss;
|
|
|
|
auto timeT = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
|
|
|
ss << std::put_time(std::gmtime(&timeT), "%c %Z");
|
|
|
|
auto timeString = ss.str();
|
2019-12-17 11:04:31 +00:00
|
|
|
newCon.verifyMessage = std::unique_ptr<char[]>(new char[4 + timeString.size()]);
|
2019-11-18 08:37:03 +00:00
|
|
|
*((uint32_t*)newCon.verifyMessage.get()) = timeString.size();
|
|
|
|
std::memcpy(newCon.verifyMessage.get() + 4, timeString.c_str(), timeString.size());
|
2019-11-21 06:15:05 +00:00
|
|
|
#ifndef NDEBUG
|
|
|
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_DEBUG,
|
|
|
|
"Client set up verification string \"",
|
|
|
|
timeString, "\"");
|
|
|
|
#endif
|
2019-11-18 08:37:03 +00:00
|
|
|
}
|
2019-11-11 07:08:51 +00:00
|
|
|
|
2019-12-17 10:12:54 +00:00
|
|
|
if(conMap.find(optE->conId) == conMap.end()) {
|
2019-11-19 11:55:20 +00:00
|
|
|
conMap.insert(std::make_pair(
|
2019-12-17 10:12:54 +00:00
|
|
|
optE->conId,
|
2019-11-19 11:55:20 +00:00
|
|
|
std::move(newCon)));
|
2019-12-17 10:12:54 +00:00
|
|
|
auto addrConIter = addrConMap.find(optE->conId.addr);
|
2019-11-19 11:55:20 +00:00
|
|
|
if(addrConIter == addrConMap.end()) {
|
|
|
|
auto insertResult = addrConMap.insert(std::make_pair(
|
2019-12-17 10:12:54 +00:00
|
|
|
optE->conId.addr,
|
2019-11-19 11:55:20 +00:00
|
|
|
std::unordered_set<UDPC_ConnectionId, UDPC::ConnectionIdHasher>{}));
|
|
|
|
assert(insertResult.second &&
|
|
|
|
"new connection insert into addrConMap must not fail");
|
|
|
|
addrConIter = insertResult.first;
|
|
|
|
}
|
2019-12-17 10:12:54 +00:00
|
|
|
addrConIter->second.insert(optE->conId);
|
2019-11-19 11:55:20 +00:00
|
|
|
UDPC_CHECK_LOG(this,
|
|
|
|
UDPC_LoggingType::UDPC_INFO,
|
|
|
|
"Client initiating connection to ",
|
2019-12-17 10:12:54 +00:00
|
|
|
UDPC_atostr((UDPC_HContext)this, optE->conId.addr),
|
2019-11-19 11:55:20 +00:00
|
|
|
" port ",
|
2019-12-17 10:12:54 +00:00
|
|
|
optE->conId.port,
|
2019-11-19 11:55:20 +00:00
|
|
|
" ...");
|
|
|
|
} else {
|
|
|
|
UDPC_CHECK_LOG(this,
|
|
|
|
UDPC_LoggingType::UDPC_WARNING,
|
|
|
|
"Client initiate connection, already connected to peer ",
|
2019-12-17 10:12:54 +00:00
|
|
|
UDPC_atostr((UDPC_HContext)this, optE->conId.addr),
|
2019-11-19 11:55:20 +00:00
|
|
|
" port ",
|
2019-12-17 10:12:54 +00:00
|
|
|
optE->conId.port);
|
2019-11-19 11:55:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case UDPC_ET_REQUEST_CONNECT_PK:
|
|
|
|
{
|
|
|
|
assert(flags.test(2) &&
|
|
|
|
"libsodium should be explictly enabled");
|
|
|
|
unsigned char *sk = nullptr;
|
|
|
|
unsigned char *pk = nullptr;
|
|
|
|
if(keysSet.load()) {
|
|
|
|
sk = this->sk;
|
|
|
|
pk = this->pk;
|
|
|
|
}
|
|
|
|
UDPC::ConnectionData newCon(
|
|
|
|
false,
|
|
|
|
this,
|
2019-12-17 10:12:54 +00:00
|
|
|
optE->conId.addr,
|
|
|
|
optE->conId.scope_id,
|
|
|
|
optE->conId.port,
|
2019-11-19 11:55:20 +00:00
|
|
|
#ifdef UDPC_LIBSODIUM_ENABLED
|
|
|
|
true,
|
|
|
|
sk, pk);
|
|
|
|
#else
|
|
|
|
false,
|
|
|
|
sk, pk);
|
|
|
|
assert(!"compiled without libsodium support");
|
2019-12-17 10:12:54 +00:00
|
|
|
delete[] optE->v.pk;
|
2019-11-19 11:55:20 +00:00
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
if(newCon.flags.test(5)) {
|
2019-12-17 10:12:54 +00:00
|
|
|
delete[] optE->v.pk;
|
2019-11-19 11:55:20 +00:00
|
|
|
UDPC_CHECK_LOG(this,
|
|
|
|
UDPC_LoggingType::UDPC_ERROR,
|
|
|
|
"Failed to init ConnectionData instance (libsodium "
|
|
|
|
"init fail) while client establishing connection with ",
|
2019-12-17 10:12:54 +00:00
|
|
|
UDPC_atostr((UDPC_HContext)this, optE->conId.addr),
|
2019-11-19 11:55:20 +00:00
|
|
|
" port ",
|
2019-12-17 10:12:54 +00:00
|
|
|
optE->conId.port);
|
2019-11-19 11:55:20 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
newCon.sent = std::chrono::steady_clock::now() - UDPC::INIT_PKT_INTERVAL_DT;
|
|
|
|
if(flags.test(2) && newCon.flags.test(6)) {
|
|
|
|
// set up verification string to send to server
|
|
|
|
std::stringstream ss;
|
|
|
|
auto timeT = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
|
|
|
ss << std::put_time(std::gmtime(&timeT), "%c %Z");
|
|
|
|
auto timeString = ss.str();
|
2019-12-17 11:04:31 +00:00
|
|
|
newCon.verifyMessage = std::unique_ptr<char[]>(new char[4 + timeString.size()]);
|
2019-11-19 11:55:20 +00:00
|
|
|
*((uint32_t*)newCon.verifyMessage.get()) = timeString.size();
|
|
|
|
std::memcpy(newCon.verifyMessage.get() + 4, timeString.c_str(), timeString.size());
|
2019-11-21 06:15:05 +00:00
|
|
|
#ifndef NDEBUG
|
|
|
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_DEBUG,
|
|
|
|
"Client set up verification string \"",
|
|
|
|
timeString, "\"");
|
|
|
|
#endif
|
2019-11-19 11:55:20 +00:00
|
|
|
|
|
|
|
// set peer public key
|
|
|
|
std::memcpy(
|
|
|
|
newCon.peer_pk,
|
2019-12-17 10:12:54 +00:00
|
|
|
optE->v.pk,
|
2019-11-19 11:55:20 +00:00
|
|
|
crypto_sign_PUBLICKEYBYTES);
|
|
|
|
newCon.flags.set(7);
|
|
|
|
}
|
|
|
|
|
2019-12-17 10:12:54 +00:00
|
|
|
delete[] optE->v.pk;
|
2019-11-19 11:55:20 +00:00
|
|
|
|
2019-12-17 10:12:54 +00:00
|
|
|
if(conMap.find(optE->conId) == conMap.end()) {
|
2019-11-11 07:08:51 +00:00
|
|
|
conMap.insert(std::make_pair(
|
2019-12-17 10:12:54 +00:00
|
|
|
optE->conId,
|
2019-11-11 07:08:51 +00:00
|
|
|
std::move(newCon)));
|
2019-12-17 10:12:54 +00:00
|
|
|
auto addrConIter = addrConMap.find(optE->conId.addr);
|
2019-11-11 07:08:51 +00:00
|
|
|
if(addrConIter == addrConMap.end()) {
|
|
|
|
auto insertResult = addrConMap.insert(std::make_pair(
|
2019-12-17 10:12:54 +00:00
|
|
|
optE->conId.addr,
|
2019-11-11 07:08:51 +00:00
|
|
|
std::unordered_set<UDPC_ConnectionId, UDPC::ConnectionIdHasher>{}));
|
|
|
|
assert(insertResult.second &&
|
|
|
|
"new connection insert into addrConMap must not fail");
|
|
|
|
addrConIter = insertResult.first;
|
|
|
|
}
|
2019-12-17 10:12:54 +00:00
|
|
|
addrConIter->second.insert(optE->conId);
|
2019-11-11 07:08:51 +00:00
|
|
|
UDPC_CHECK_LOG(this,
|
|
|
|
UDPC_LoggingType::UDPC_INFO,
|
|
|
|
"Client initiating connection to ",
|
2019-12-17 10:12:54 +00:00
|
|
|
UDPC_atostr((UDPC_HContext)this, optE->conId.addr),
|
2019-11-11 07:08:51 +00:00
|
|
|
" port ",
|
2019-12-17 10:12:54 +00:00
|
|
|
optE->conId.port,
|
2019-11-11 07:08:51 +00:00
|
|
|
" ...");
|
|
|
|
} else {
|
|
|
|
UDPC_CHECK_LOG(this,
|
|
|
|
UDPC_LoggingType::UDPC_WARNING,
|
|
|
|
"Client initiate connection, already connected to peer ",
|
2019-12-17 10:12:54 +00:00
|
|
|
UDPC_atostr((UDPC_HContext)this, optE->conId.addr),
|
2019-11-11 07:08:51 +00:00
|
|
|
" port ",
|
2019-12-17 10:12:54 +00:00
|
|
|
optE->conId.port);
|
2019-11-11 07:08:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case UDPC_ET_REQUEST_DISCONNECT:
|
2019-12-17 10:12:54 +00:00
|
|
|
if(optE->v.dropAllWithAddr != 0) {
|
2019-11-11 07:08:51 +00:00
|
|
|
// drop all connections with same address
|
2019-12-17 10:12:54 +00:00
|
|
|
auto addrConIter = addrConMap.find(optE->conId.addr);
|
2019-11-11 07:08:51 +00:00
|
|
|
if(addrConIter != addrConMap.end()) {
|
|
|
|
for(auto identIter = addrConIter->second.begin();
|
|
|
|
identIter != addrConIter->second.end();
|
|
|
|
++identIter) {
|
2019-12-17 11:04:31 +00:00
|
|
|
assert(conMap.find(*identIter) != conMap.end()
|
|
|
|
&& "conMap must have connection listed in "
|
|
|
|
"addrConMap");
|
|
|
|
deletionMap.insert(*identIter);
|
2019-11-11 07:08:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// drop only specific connection with addr and port
|
2019-12-17 10:12:54 +00:00
|
|
|
auto iter = conMap.find(optE->conId);
|
2019-11-11 07:08:51 +00:00
|
|
|
if(iter != conMap.end()) {
|
2019-12-17 11:04:31 +00:00
|
|
|
deletionMap.insert(iter->first);
|
2019-11-11 07:08:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
assert(!"internalEvents got invalid type");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} while(!internalEvents.empty());
|
|
|
|
|
2019-07-25 11:51:08 +00:00
|
|
|
{
|
|
|
|
// check timed out, check good/bad mode with rtt, remove timed out
|
2019-09-03 03:06:46 +00:00
|
|
|
std::vector<UDPC_ConnectionId> removed;
|
2019-09-16 02:40:43 +00:00
|
|
|
for(auto iter = conMap.begin(); iter != conMap.end(); ++iter) {
|
2019-08-27 07:31:24 +00:00
|
|
|
temp_dt_fs = now - iter->second.received;
|
|
|
|
if(temp_dt_fs >= UDPC::CONNECTION_TIMEOUT) {
|
2019-07-25 11:51:08 +00:00
|
|
|
removed.push_back(iter->first);
|
2019-09-20 05:26:59 +00:00
|
|
|
UDPC_CHECK_LOG(this,
|
2019-09-19 01:58:19 +00:00
|
|
|
UDPC_LoggingType::UDPC_VERBOSE,
|
2019-08-29 03:56:09 +00:00
|
|
|
"Timed out connection with ",
|
2019-09-18 08:35:14 +00:00
|
|
|
UDPC_atostr((UDPC_HContext)this, iter->first.addr),
|
2019-09-17 11:33:47 +00:00
|
|
|
", port = ",
|
2019-08-29 03:56:09 +00:00
|
|
|
iter->second.port);
|
2019-07-25 11:51:08 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// check good/bad mode
|
2019-09-18 02:42:16 +00:00
|
|
|
iter->second.toggleTimer += dt;
|
|
|
|
iter->second.toggledTimer += dt;
|
2019-07-25 11:51:08 +00:00
|
|
|
if(iter->second.flags.test(1) && !iter->second.flags.test(2)) {
|
|
|
|
// good mode, bad rtt
|
2019-09-20 05:26:59 +00:00
|
|
|
UDPC_CHECK_LOG(this,
|
2019-11-06 05:35:16 +00:00
|
|
|
UDPC_LoggingType::UDPC_VERBOSE,
|
2019-08-29 03:56:09 +00:00
|
|
|
"Switching to bad mode in connection with ",
|
2019-09-18 08:35:14 +00:00
|
|
|
UDPC_atostr((UDPC_HContext)this, iter->first.addr),
|
2019-09-17 11:33:47 +00:00
|
|
|
", port = ",
|
2019-08-29 03:56:09 +00:00
|
|
|
iter->second.port);
|
2019-07-25 11:51:08 +00:00
|
|
|
iter->second.flags.reset(1);
|
2019-08-27 07:31:24 +00:00
|
|
|
if(iter->second.toggledTimer <= UDPC::TEN_SECONDS) {
|
|
|
|
iter->second.toggleT *= 2;
|
2019-07-25 11:51:08 +00:00
|
|
|
}
|
2019-08-27 07:31:24 +00:00
|
|
|
iter->second.toggledTimer = std::chrono::steady_clock::duration::zero();
|
2019-11-11 07:08:51 +00:00
|
|
|
if(isReceivingEvents.load()) {
|
|
|
|
externalEvents.push(UDPC_Event{
|
|
|
|
UDPC_ET_BAD_MODE, iter->first, false});
|
|
|
|
}
|
2019-07-25 11:51:08 +00:00
|
|
|
} else if(iter->second.flags.test(1)) {
|
|
|
|
// good mode, good rtt
|
2019-08-27 07:31:24 +00:00
|
|
|
if(iter->second.toggleTimer >= UDPC::TEN_SECONDS) {
|
|
|
|
iter->second.toggleTimer = std::chrono::steady_clock::duration::zero();
|
|
|
|
iter->second.toggleT /= 2;
|
|
|
|
if(iter->second.toggleT < UDPC::ONE_SECOND) {
|
|
|
|
iter->second.toggleT = UDPC::ONE_SECOND;
|
2019-07-25 11:51:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if(!iter->second.flags.test(1) &&
|
|
|
|
iter->second.flags.test(2)) {
|
|
|
|
// bad mode, good rtt
|
|
|
|
if(iter->second.toggledTimer >= iter->second.toggleT) {
|
2019-08-27 07:31:24 +00:00
|
|
|
iter->second.toggleTimer = std::chrono::steady_clock::duration::zero();
|
|
|
|
iter->second.toggledTimer = std::chrono::steady_clock::duration::zero();
|
2019-09-20 05:26:59 +00:00
|
|
|
UDPC_CHECK_LOG(this,
|
2019-11-06 05:35:16 +00:00
|
|
|
UDPC_LoggingType::UDPC_VERBOSE,
|
2019-08-29 03:56:09 +00:00
|
|
|
"Switching to good mode in connection with ",
|
2019-09-18 08:35:14 +00:00
|
|
|
UDPC_atostr((UDPC_HContext)this, iter->first.addr),
|
2019-09-17 11:33:47 +00:00
|
|
|
", port = ",
|
2019-08-29 03:56:09 +00:00
|
|
|
iter->second.port);
|
2019-07-25 11:51:08 +00:00
|
|
|
iter->second.flags.set(1);
|
2019-11-11 07:08:51 +00:00
|
|
|
if(isReceivingEvents.load()) {
|
|
|
|
externalEvents.push(UDPC_Event{
|
|
|
|
UDPC_ET_GOOD_MODE, iter->first, false});
|
|
|
|
}
|
2019-07-25 11:51:08 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// bad mode, bad rtt
|
2019-08-27 07:31:24 +00:00
|
|
|
iter->second.toggledTimer = std::chrono::steady_clock::duration::zero();
|
2019-07-25 11:51:08 +00:00
|
|
|
}
|
|
|
|
|
2019-09-18 02:42:16 +00:00
|
|
|
iter->second.timer += dt;
|
2019-09-17 11:33:47 +00:00
|
|
|
if(iter->second.flags.test(1)) {
|
|
|
|
if(iter->second.timer >= UDPC::GOOD_MODE_SEND_RATE) {
|
|
|
|
iter->second.timer -= UDPC::GOOD_MODE_SEND_RATE;
|
|
|
|
iter->second.flags.set(0);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if(iter->second.timer >= UDPC::BAD_MODE_SEND_RATE) {
|
|
|
|
iter->second.timer -= UDPC::BAD_MODE_SEND_RATE;
|
|
|
|
iter->second.flags.set(0);
|
|
|
|
}
|
2019-07-25 11:51:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
for(auto iter = removed.begin(); iter != removed.end(); ++iter) {
|
2019-09-16 02:40:43 +00:00
|
|
|
auto addrConIter = addrConMap.find(iter->addr);
|
|
|
|
assert(addrConIter != addrConMap.end()
|
2019-08-28 07:38:14 +00:00
|
|
|
&& "addrConMap must have an entry for a current connection");
|
|
|
|
auto addrConSetIter = addrConIter->second.find(*iter);
|
|
|
|
assert(addrConSetIter != addrConIter->second.end()
|
|
|
|
&& "nested set in addrConMap must have an entry for a current connection");
|
|
|
|
addrConIter->second.erase(addrConSetIter);
|
|
|
|
if(addrConIter->second.empty()) {
|
2019-09-16 02:40:43 +00:00
|
|
|
addrConMap.erase(addrConIter);
|
2019-08-28 07:38:14 +00:00
|
|
|
}
|
|
|
|
|
2019-09-16 02:40:43 +00:00
|
|
|
auto cIter = conMap.find(*iter);
|
|
|
|
assert(cIter != conMap.end()
|
2019-08-28 07:38:14 +00:00
|
|
|
&& "conMap must have the entry set to be removed");
|
|
|
|
|
2019-07-25 11:51:08 +00:00
|
|
|
if(cIter->second.flags.test(4)) {
|
2019-09-16 02:40:43 +00:00
|
|
|
idMap.erase(cIter->second.id);
|
2019-07-25 11:51:08 +00:00
|
|
|
}
|
2019-11-11 07:08:51 +00:00
|
|
|
if(isReceivingEvents.load()) {
|
|
|
|
externalEvents.push(UDPC_Event{
|
|
|
|
UDPC_ET_DISCONNECTED, *iter, false});
|
|
|
|
}
|
2019-08-28 07:38:14 +00:00
|
|
|
|
2019-09-16 02:40:43 +00:00
|
|
|
conMap.erase(cIter);
|
2019-07-25 11:51:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-27 11:19:48 +00:00
|
|
|
// move queued in cSendPkts to existing connection's sendPkts
|
|
|
|
{
|
2019-11-06 05:35:16 +00:00
|
|
|
auto sendIter = cSendPkts.begin();
|
2019-11-11 07:08:51 +00:00
|
|
|
std::unordered_set<UDPC_ConnectionId, UDPC::ConnectionIdHasher> dropped;
|
2019-11-21 06:15:05 +00:00
|
|
|
std::unordered_set<UDPC_ConnectionId, UDPC::ConnectionIdHasher> notQueued;
|
2019-11-06 05:35:16 +00:00
|
|
|
while(true) {
|
|
|
|
auto next = sendIter.current();
|
2019-09-27 11:19:48 +00:00
|
|
|
if(next) {
|
2019-12-17 10:12:54 +00:00
|
|
|
auto iter = conMap.find(next->receiver);
|
2019-12-11 11:00:48 +00:00
|
|
|
if(iter != conMap.end()) {
|
2019-11-06 05:35:16 +00:00
|
|
|
if(iter->second.sendPkts.size() >= UDPC_QUEUED_PKTS_MAX_SIZE) {
|
2019-12-17 10:12:54 +00:00
|
|
|
if(notQueued.find(next->receiver) == notQueued.end()) {
|
|
|
|
notQueued.insert(next->receiver);
|
2019-11-21 06:15:05 +00:00
|
|
|
UDPC_CHECK_LOG(this,
|
|
|
|
UDPC_LoggingType::UDPC_DEBUG,
|
|
|
|
"Not queueing packet to ",
|
|
|
|
UDPC_atostr((UDPC_HContext)this,
|
2019-12-17 10:12:54 +00:00
|
|
|
next->receiver.addr),
|
2019-11-21 06:15:05 +00:00
|
|
|
", port = ",
|
2019-12-17 10:12:54 +00:00
|
|
|
next->receiver.port,
|
2019-11-21 06:15:05 +00:00
|
|
|
", connection's queue reached max size");
|
|
|
|
}
|
2019-11-06 05:35:16 +00:00
|
|
|
if(sendIter.next()) {
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2019-12-17 10:12:54 +00:00
|
|
|
iter->second.sendPkts.push_back(*next);
|
2019-11-06 05:35:16 +00:00
|
|
|
if(sendIter.remove()) {
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
2019-09-27 11:19:48 +00:00
|
|
|
} else {
|
2019-12-17 10:12:54 +00:00
|
|
|
if(dropped.find(next->receiver) == dropped.end()) {
|
2019-11-11 07:08:51 +00:00
|
|
|
UDPC_CHECK_LOG(this,
|
|
|
|
UDPC_LoggingType::UDPC_WARNING,
|
|
|
|
"Dropped queued packets to ",
|
|
|
|
UDPC_atostr(
|
|
|
|
(UDPC_HContext)this,
|
2019-12-17 10:12:54 +00:00
|
|
|
next->receiver.addr),
|
2019-11-11 07:08:51 +00:00
|
|
|
", port = ",
|
2019-12-17 10:12:54 +00:00
|
|
|
next->receiver.port,
|
2019-11-11 07:08:51 +00:00
|
|
|
" due to connection not existing");
|
2019-12-17 10:12:54 +00:00
|
|
|
dropped.insert(next->receiver);
|
2019-11-11 07:08:51 +00:00
|
|
|
}
|
2019-11-06 05:35:16 +00:00
|
|
|
if(sendIter.remove()) {
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
2019-09-27 11:19:48 +00:00
|
|
|
}
|
2019-11-06 05:35:16 +00:00
|
|
|
} else {
|
|
|
|
break;
|
2019-09-27 11:19:48 +00:00
|
|
|
}
|
2019-11-06 05:35:16 +00:00
|
|
|
}
|
2019-09-27 11:19:48 +00:00
|
|
|
}
|
|
|
|
|
2019-07-25 11:51:08 +00:00
|
|
|
// update send (only if triggerSend flag is set)
|
2019-09-16 02:40:43 +00:00
|
|
|
for(auto iter = conMap.begin(); iter != conMap.end(); ++iter) {
|
2019-12-17 11:04:31 +00:00
|
|
|
auto delIter = deletionMap.find(iter->first);
|
|
|
|
if(!iter->second.flags.test(0) && delIter == deletionMap.end()) {
|
|
|
|
continue;
|
|
|
|
} else if(delIter != deletionMap.end()) {
|
|
|
|
if(iter->second.flags.test(3)) {
|
|
|
|
// not initiated connection yet, no need to send disconnect pkt
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
unsigned int sendSize = 0;
|
|
|
|
std::unique_ptr<char[]> buf;
|
|
|
|
if(flags.test(2) && iter->second.flags.test(6)) {
|
|
|
|
sendSize = UDPC_LSFULL_HEADER_SIZE;
|
|
|
|
buf = std::unique_ptr<char[]>(new char[sendSize]);
|
|
|
|
*((unsigned char*)(buf.get() + UDPC_MIN_HEADER_SIZE)) = 1;
|
|
|
|
} else {
|
|
|
|
sendSize = UDPC_NSFULL_HEADER_SIZE;
|
|
|
|
buf = std::unique_ptr<char[]>(new char[sendSize]);
|
|
|
|
*((unsigned char*)(buf.get() + UDPC_MIN_HEADER_SIZE)) = 0;
|
|
|
|
}
|
|
|
|
UDPC::preparePacket(
|
|
|
|
buf.get(),
|
|
|
|
protocolID,
|
|
|
|
iter->second.id,
|
|
|
|
iter->second.rseq,
|
|
|
|
iter->second.ack,
|
|
|
|
&iter->second.lseq,
|
|
|
|
0x3);
|
|
|
|
if(flags.test(2) && iter->second.flags.test(6)) {
|
|
|
|
#ifdef UDPC_LIBSODIUM_ENABLED
|
|
|
|
if(crypto_sign_detached(
|
|
|
|
(unsigned char*)(buf.get() + UDPC_MIN_HEADER_SIZE + 1), nullptr,
|
|
|
|
(unsigned char*)buf.get(), UDPC_MIN_HEADER_SIZE,
|
|
|
|
iter->second.sk) != 0) {
|
|
|
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
|
|
|
|
"Failed to sign packet for peer ",
|
|
|
|
UDPC_atostr((UDPC_HContext)this, iter->first.addr),
|
|
|
|
", port ",
|
|
|
|
iter->second.port);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
assert(!"libsodium disabled, invalid state");
|
|
|
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
|
|
|
|
"libsodium is disabled, cannot send packet");
|
|
|
|
continue;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
UDPC_IPV6_SOCKADDR_TYPE destinationInfo;
|
|
|
|
destinationInfo.sin6_family = AF_INET6;
|
|
|
|
std::memcpy(
|
|
|
|
UDPC_IPV6_ADDR_SUB(destinationInfo.sin6_addr),
|
|
|
|
UDPC_IPV6_ADDR_SUB(iter->first.addr),
|
|
|
|
16);
|
|
|
|
destinationInfo.sin6_port = htons(iter->second.port);
|
|
|
|
destinationInfo.sin6_flowinfo = 0;
|
|
|
|
destinationInfo.sin6_scope_id = iter->first.scope_id;
|
|
|
|
long int sentBytes = sendto(
|
|
|
|
socketHandle,
|
|
|
|
buf.get(),
|
|
|
|
sendSize,
|
|
|
|
0,
|
|
|
|
(struct sockaddr*) &destinationInfo,
|
|
|
|
sizeof(UDPC_IPV6_SOCKADDR_TYPE));
|
|
|
|
if(sentBytes != sendSize) {
|
|
|
|
UDPC_CHECK_LOG(this,
|
|
|
|
UDPC_LoggingType::UDPC_ERROR,
|
|
|
|
"Failed to send disconnect packet to ",
|
|
|
|
UDPC_atostr((UDPC_HContext)this, iter->first.addr),
|
|
|
|
", port = ",
|
|
|
|
iter->second.port);
|
|
|
|
continue;
|
|
|
|
}
|
2019-07-25 11:51:08 +00:00
|
|
|
continue;
|
2019-07-21 05:29:31 +00:00
|
|
|
}
|
2019-12-17 11:04:31 +00:00
|
|
|
|
|
|
|
// clear triggerSend flag
|
2019-07-25 11:51:08 +00:00
|
|
|
iter->second.flags.reset(0);
|
|
|
|
|
|
|
|
if(iter->second.flags.test(3)) {
|
2019-09-16 02:40:43 +00:00
|
|
|
if(flags.test(1)) {
|
2019-07-25 11:51:08 +00:00
|
|
|
// is initiating connection to server
|
|
|
|
auto initDT = now - iter->second.sent;
|
|
|
|
if(initDT < UDPC::INIT_PKT_INTERVAL_DT) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
iter->second.sent = now;
|
|
|
|
|
2019-11-18 08:37:03 +00:00
|
|
|
std::unique_ptr<char[]> buf;
|
|
|
|
unsigned int sendSize = 0;
|
|
|
|
if(flags.test(2) && iter->second.flags.test(6)) {
|
|
|
|
#ifdef UDPC_LIBSODIUM_ENABLED
|
|
|
|
assert(iter->second.verifyMessage
|
|
|
|
&& "Verify message should already exist");
|
|
|
|
sendSize = UDPC_CCL_HEADER_SIZE + *((uint32_t*)iter->second.verifyMessage.get());
|
2019-12-17 11:04:31 +00:00
|
|
|
buf = std::unique_ptr<char[]>(new char[sendSize]);
|
2019-11-18 08:37:03 +00:00
|
|
|
// set type 1
|
|
|
|
*((uint32_t*)(buf.get() + UDPC_MIN_HEADER_SIZE)) = htonl(1);
|
|
|
|
// set public key
|
|
|
|
std::memcpy(
|
|
|
|
buf.get() + UDPC_MIN_HEADER_SIZE + 4,
|
|
|
|
iter->second.pk,
|
|
|
|
crypto_sign_PUBLICKEYBYTES);
|
|
|
|
// set verify message size
|
|
|
|
uint32_t temp = htonl(*((uint32_t*)iter->second.verifyMessage.get()));
|
|
|
|
std::memcpy(
|
|
|
|
buf.get() + UDPC_MIN_HEADER_SIZE + 4 + crypto_sign_PUBLICKEYBYTES,
|
|
|
|
&temp,
|
|
|
|
4);
|
|
|
|
// set verify message
|
|
|
|
std::memcpy(
|
|
|
|
buf.get() + UDPC_MIN_HEADER_SIZE + 4 + crypto_sign_PUBLICKEYBYTES + 4,
|
|
|
|
iter->second.verifyMessage.get() + 4,
|
|
|
|
*((uint32_t*)iter->second.verifyMessage.get()));
|
|
|
|
#else
|
|
|
|
assert(!"libsodium is disabled, invalid state");
|
|
|
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
|
|
|
|
"libsodium is disabled, cannot send packet");
|
|
|
|
continue;
|
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
sendSize = UDPC_CON_HEADER_SIZE;
|
2019-12-17 11:04:31 +00:00
|
|
|
buf = std::unique_ptr<char[]>(new char[sendSize]);
|
2019-11-18 08:37:03 +00:00
|
|
|
*((uint32_t*)(buf.get() + 20)) = 0;
|
|
|
|
}
|
2019-07-25 11:51:08 +00:00
|
|
|
UDPC::preparePacket(
|
|
|
|
buf.get(),
|
2019-09-16 02:40:43 +00:00
|
|
|
protocolID,
|
2019-07-25 11:51:08 +00:00
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0xFFFFFFFF,
|
|
|
|
nullptr,
|
2019-11-18 08:37:03 +00:00
|
|
|
0x1);
|
2019-07-25 11:51:08 +00:00
|
|
|
|
2019-09-19 03:23:15 +00:00
|
|
|
UDPC_IPV6_SOCKADDR_TYPE destinationInfo;
|
2019-09-07 07:36:11 +00:00
|
|
|
destinationInfo.sin6_family = AF_INET6;
|
2019-09-19 03:23:15 +00:00
|
|
|
std::memcpy(UDPC_IPV6_ADDR_SUB(destinationInfo.sin6_addr), UDPC_IPV6_ADDR_SUB(iter->first.addr), 16);
|
2019-09-07 07:36:11 +00:00
|
|
|
destinationInfo.sin6_port = htons(iter->second.port);
|
2019-09-17 11:33:47 +00:00
|
|
|
destinationInfo.sin6_flowinfo = 0;
|
2019-09-18 08:35:14 +00:00
|
|
|
destinationInfo.sin6_scope_id = iter->first.scope_id;
|
2019-07-25 11:51:08 +00:00
|
|
|
long int sentBytes = sendto(
|
2019-09-16 02:40:43 +00:00
|
|
|
socketHandle,
|
2019-07-25 11:51:08 +00:00
|
|
|
buf.get(),
|
2019-11-18 08:37:03 +00:00
|
|
|
sendSize,
|
2019-07-25 11:51:08 +00:00
|
|
|
0,
|
|
|
|
(struct sockaddr*) &destinationInfo,
|
2019-09-19 03:23:15 +00:00
|
|
|
sizeof(UDPC_IPV6_SOCKADDR_TYPE));
|
2019-11-18 08:37:03 +00:00
|
|
|
if(sentBytes != sendSize) {
|
2019-09-20 05:26:59 +00:00
|
|
|
UDPC_CHECK_LOG(this,
|
2019-09-19 01:58:19 +00:00
|
|
|
UDPC_LoggingType::UDPC_ERROR,
|
2019-08-29 03:56:09 +00:00
|
|
|
"Failed to send packet to initiate connection to ",
|
2019-09-18 08:35:14 +00:00
|
|
|
UDPC_atostr((UDPC_HContext)this, iter->first.addr),
|
2019-09-17 11:33:47 +00:00
|
|
|
", port = ",
|
2019-08-29 03:56:09 +00:00
|
|
|
iter->second.port);
|
2019-08-28 06:54:18 +00:00
|
|
|
continue;
|
2019-09-17 11:33:47 +00:00
|
|
|
} else {
|
2019-09-20 05:26:59 +00:00
|
|
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_INFO, "Sent initiate connection to ",
|
2019-09-18 08:35:14 +00:00
|
|
|
UDPC_atostr((UDPC_HContext)this, iter->first.addr),
|
2019-11-18 08:37:03 +00:00
|
|
|
", port = ", iter->second.port,
|
|
|
|
flags.test(2) && iter->second.flags.test(6) ?
|
|
|
|
", libsodium enabled" : ", libsodium disabled");
|
2019-07-25 11:51:08 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// is server, initiate connection to client
|
|
|
|
iter->second.flags.reset(3);
|
|
|
|
iter->second.sent = now;
|
|
|
|
|
2019-11-18 08:37:03 +00:00
|
|
|
std::unique_ptr<char[]> buf;
|
|
|
|
unsigned int sendSize = 0;
|
|
|
|
if(flags.test(2) && iter->second.flags.test(6)) {
|
|
|
|
#ifdef UDPC_LIBSODIUM_ENABLED
|
|
|
|
sendSize = UDPC_CSR_HEADER_SIZE;
|
2019-12-17 11:04:31 +00:00
|
|
|
buf = std::unique_ptr<char[]>(new char[sendSize]);
|
2019-11-18 08:37:03 +00:00
|
|
|
// set type
|
|
|
|
*((uint32_t*)(buf.get() + UDPC_MIN_HEADER_SIZE)) = htonl(2);
|
|
|
|
// set pubkey
|
|
|
|
std::memcpy(buf.get() + UDPC_MIN_HEADER_SIZE + 4,
|
|
|
|
iter->second.pk,
|
|
|
|
crypto_sign_PUBLICKEYBYTES);
|
|
|
|
// set detached sig
|
|
|
|
assert(iter->second.verifyMessage &&
|
|
|
|
"Detached sig in verifyMessage must exist");
|
|
|
|
std::memcpy(
|
|
|
|
buf.get() + UDPC_MIN_HEADER_SIZE + 4 + crypto_sign_PUBLICKEYBYTES,
|
|
|
|
iter->second.verifyMessage.get(),
|
|
|
|
crypto_sign_BYTES);
|
|
|
|
#else
|
|
|
|
assert(!"libsodium disabled, invalid state");
|
|
|
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
|
|
|
|
"libsodium is disabled, cannot send packet");
|
|
|
|
continue;
|
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
sendSize = UDPC_CON_HEADER_SIZE;
|
2019-12-17 11:04:31 +00:00
|
|
|
buf = std::unique_ptr<char[]>(new char[sendSize]);
|
2019-11-18 08:37:03 +00:00
|
|
|
*((uint32_t*)(buf.get() + UDPC_MIN_HEADER_SIZE)) = 0;
|
|
|
|
}
|
2019-07-25 11:51:08 +00:00
|
|
|
UDPC::preparePacket(
|
|
|
|
buf.get(),
|
2019-09-16 02:40:43 +00:00
|
|
|
protocolID,
|
2019-07-25 11:51:08 +00:00
|
|
|
iter->second.id,
|
|
|
|
iter->second.rseq,
|
|
|
|
iter->second.ack,
|
|
|
|
&iter->second.lseq,
|
2019-11-18 08:37:03 +00:00
|
|
|
0x1);
|
2019-07-25 11:51:08 +00:00
|
|
|
|
2019-09-19 03:23:15 +00:00
|
|
|
UDPC_IPV6_SOCKADDR_TYPE destinationInfo;
|
2019-09-07 07:36:11 +00:00
|
|
|
destinationInfo.sin6_family = AF_INET6;
|
2019-09-19 03:23:15 +00:00
|
|
|
std::memcpy(UDPC_IPV6_ADDR_SUB(destinationInfo.sin6_addr), UDPC_IPV6_ADDR_SUB(iter->first.addr), 16);
|
2019-09-07 07:36:11 +00:00
|
|
|
destinationInfo.sin6_port = htons(iter->second.port);
|
2019-09-17 11:33:47 +00:00
|
|
|
destinationInfo.sin6_flowinfo = 0;
|
2019-09-18 08:35:14 +00:00
|
|
|
destinationInfo.sin6_scope_id = iter->first.scope_id;
|
2019-07-25 11:51:08 +00:00
|
|
|
long int sentBytes = sendto(
|
2019-09-16 02:40:43 +00:00
|
|
|
socketHandle,
|
2019-07-25 11:51:08 +00:00
|
|
|
buf.get(),
|
2019-11-18 08:37:03 +00:00
|
|
|
sendSize,
|
2019-07-25 11:51:08 +00:00
|
|
|
0,
|
|
|
|
(struct sockaddr*) &destinationInfo,
|
2019-09-19 03:23:15 +00:00
|
|
|
sizeof(UDPC_IPV6_SOCKADDR_TYPE));
|
2019-11-18 08:37:03 +00:00
|
|
|
if(sentBytes != sendSize) {
|
2019-09-20 05:26:59 +00:00
|
|
|
UDPC_CHECK_LOG(this,
|
2019-09-19 01:58:19 +00:00
|
|
|
UDPC_LoggingType::UDPC_ERROR,
|
2019-08-29 03:56:09 +00:00
|
|
|
"Failed to send packet to initiate connection to ",
|
2019-09-18 08:35:14 +00:00
|
|
|
UDPC_atostr((UDPC_HContext)this, iter->first.addr),
|
2019-09-17 11:33:47 +00:00
|
|
|
", port = ",
|
2019-08-29 03:56:09 +00:00
|
|
|
iter->second.port);
|
2019-08-28 06:54:18 +00:00
|
|
|
continue;
|
2019-07-25 11:51:08 +00:00
|
|
|
}
|
2019-11-18 08:37:03 +00:00
|
|
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_DEBUG,
|
|
|
|
"Sent init pkt to client ",
|
|
|
|
UDPC_atostr((UDPC_HContext)this, destinationInfo.sin6_addr),
|
|
|
|
", port ", iter->second.port);
|
2019-07-25 11:51:08 +00:00
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Not initiating connection, send as normal on current connection
|
|
|
|
if(iter->second.sendPkts.empty() && iter->second.priorityPkts.empty()) {
|
|
|
|
// nothing in queues, send heartbeat packet
|
|
|
|
auto sentDT = now - iter->second.sent;
|
|
|
|
if(sentDT < UDPC::HEARTBEAT_PKT_INTERVAL_DT) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-11-18 08:37:03 +00:00
|
|
|
unsigned int sendSize = 0;
|
|
|
|
std::unique_ptr<char[]> buf;
|
|
|
|
if(flags.test(2) && iter->second.flags.test(6)) {
|
|
|
|
sendSize = UDPC_LSFULL_HEADER_SIZE;
|
2019-12-17 11:04:31 +00:00
|
|
|
buf = std::unique_ptr<char[]>(new char[sendSize]);
|
2019-11-18 08:37:03 +00:00
|
|
|
*((unsigned char*)(buf.get() + UDPC_MIN_HEADER_SIZE)) = 1;
|
|
|
|
} else {
|
|
|
|
sendSize = UDPC_NSFULL_HEADER_SIZE;
|
2019-12-17 11:04:31 +00:00
|
|
|
buf = std::unique_ptr<char[]>(new char[sendSize]);
|
2019-11-18 08:37:03 +00:00
|
|
|
*((unsigned char*)(buf.get() + UDPC_MIN_HEADER_SIZE)) = 0;
|
|
|
|
}
|
2019-07-25 11:51:08 +00:00
|
|
|
UDPC::preparePacket(
|
|
|
|
buf.get(),
|
2019-09-16 02:40:43 +00:00
|
|
|
protocolID,
|
2019-07-25 11:51:08 +00:00
|
|
|
iter->second.id,
|
|
|
|
iter->second.rseq,
|
|
|
|
iter->second.ack,
|
|
|
|
&iter->second.lseq,
|
2019-11-18 08:37:03 +00:00
|
|
|
0);
|
|
|
|
if(flags.test(2) && iter->second.flags.test(6)) {
|
|
|
|
#ifdef UDPC_LIBSODIUM_ENABLED
|
|
|
|
if(crypto_sign_detached(
|
|
|
|
(unsigned char*)(buf.get() + UDPC_MIN_HEADER_SIZE + 1), nullptr,
|
|
|
|
(unsigned char*)buf.get(), UDPC_MIN_HEADER_SIZE,
|
|
|
|
iter->second.sk) != 0) {
|
|
|
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
|
|
|
|
"Failed to sign packet for peer ",
|
|
|
|
UDPC_atostr((UDPC_HContext)this, iter->first.addr),
|
|
|
|
", port ",
|
|
|
|
iter->second.port);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
assert(!"libsodium disabled, invalid state");
|
|
|
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
|
|
|
|
"libsodium is disabled, cannot send packet");
|
|
|
|
continue;
|
|
|
|
#endif
|
|
|
|
}
|
2019-07-25 11:51:08 +00:00
|
|
|
|
2019-09-19 03:23:15 +00:00
|
|
|
UDPC_IPV6_SOCKADDR_TYPE destinationInfo;
|
2019-09-07 07:36:11 +00:00
|
|
|
destinationInfo.sin6_family = AF_INET6;
|
2019-09-20 05:01:26 +00:00
|
|
|
std::memcpy(
|
|
|
|
UDPC_IPV6_ADDR_SUB(destinationInfo.sin6_addr),
|
|
|
|
UDPC_IPV6_ADDR_SUB(iter->first.addr),
|
|
|
|
16);
|
2019-09-07 07:36:11 +00:00
|
|
|
destinationInfo.sin6_port = htons(iter->second.port);
|
2019-09-17 11:33:47 +00:00
|
|
|
destinationInfo.sin6_flowinfo = 0;
|
2019-09-18 08:35:14 +00:00
|
|
|
destinationInfo.sin6_scope_id = iter->first.scope_id;
|
2019-07-25 11:51:08 +00:00
|
|
|
long int sentBytes = sendto(
|
2019-09-16 02:40:43 +00:00
|
|
|
socketHandle,
|
2019-07-25 11:51:08 +00:00
|
|
|
buf.get(),
|
2019-11-18 08:37:03 +00:00
|
|
|
sendSize,
|
2019-07-25 11:51:08 +00:00
|
|
|
0,
|
|
|
|
(struct sockaddr*) &destinationInfo,
|
2019-09-19 03:23:15 +00:00
|
|
|
sizeof(UDPC_IPV6_SOCKADDR_TYPE));
|
2019-11-18 08:37:03 +00:00
|
|
|
if(sentBytes != sendSize) {
|
2019-09-20 05:26:59 +00:00
|
|
|
UDPC_CHECK_LOG(this,
|
2019-09-19 01:58:19 +00:00
|
|
|
UDPC_LoggingType::UDPC_ERROR,
|
2019-08-29 03:56:09 +00:00
|
|
|
"Failed to send heartbeat packet to ",
|
2019-09-18 08:35:14 +00:00
|
|
|
UDPC_atostr((UDPC_HContext)this, iter->first.addr),
|
2019-09-17 11:33:47 +00:00
|
|
|
", port = ",
|
2019-08-29 03:56:09 +00:00
|
|
|
iter->second.port);
|
2019-08-28 06:54:18 +00:00
|
|
|
continue;
|
2019-07-25 11:51:08 +00:00
|
|
|
}
|
|
|
|
|
2019-09-07 07:36:11 +00:00
|
|
|
UDPC_PacketInfo pInfo = UDPC::get_empty_pinfo();
|
2019-09-20 05:01:26 +00:00
|
|
|
pInfo.flags = 0x4;
|
2019-09-07 07:36:11 +00:00
|
|
|
pInfo.sender.addr = in6addr_loopback;
|
2019-09-03 03:06:46 +00:00
|
|
|
pInfo.receiver.addr = iter->first.addr;
|
2019-09-23 11:11:12 +00:00
|
|
|
pInfo.sender.port = ntohs(socketInfo.sin6_port);
|
2019-09-03 03:06:46 +00:00
|
|
|
pInfo.receiver.port = iter->second.port;
|
2019-09-17 11:33:47 +00:00
|
|
|
*((uint32_t*)(pInfo.data + 8)) = htonl(iter->second.lseq - 1);
|
2019-11-18 08:37:03 +00:00
|
|
|
pInfo.data[UDPC_MIN_HEADER_SIZE] = flags.test(2) && iter->second.flags.test(6) ? 1 : 0;
|
2019-07-21 05:29:31 +00:00
|
|
|
|
2019-07-25 11:51:08 +00:00
|
|
|
iter->second.sentPkts.push_back(std::move(pInfo));
|
2019-08-22 11:16:07 +00:00
|
|
|
iter->second.cleanupSentPkts();
|
|
|
|
|
|
|
|
// store other pkt info
|
|
|
|
UDPC::SentPktInfo::Ptr sentPktInfo = std::make_shared<UDPC::SentPktInfo>();
|
|
|
|
sentPktInfo->id = iter->second.lseq - 1;
|
|
|
|
iter->second.sentInfoMap.insert(std::make_pair(sentPktInfo->id, sentPktInfo));
|
2019-07-25 11:51:08 +00:00
|
|
|
} else {
|
|
|
|
// sendPkts or priorityPkts not empty
|
2019-09-07 07:36:11 +00:00
|
|
|
UDPC_PacketInfo pInfo = UDPC::get_empty_pinfo();
|
2019-07-25 11:51:08 +00:00
|
|
|
bool isResending = false;
|
|
|
|
if(!iter->second.priorityPkts.empty()) {
|
2019-09-27 11:19:48 +00:00
|
|
|
pInfo = iter->second.priorityPkts.front();
|
|
|
|
iter->second.priorityPkts.pop_front();
|
2019-07-25 11:51:08 +00:00
|
|
|
isResending = true;
|
|
|
|
} else {
|
2019-09-27 11:19:48 +00:00
|
|
|
pInfo = iter->second.sendPkts.front();
|
|
|
|
iter->second.sendPkts.pop_front();
|
2019-07-25 11:51:08 +00:00
|
|
|
}
|
2019-11-18 08:37:03 +00:00
|
|
|
|
|
|
|
std::unique_ptr<char[]> buf;
|
|
|
|
unsigned int sendSize = 0;
|
|
|
|
if(flags.test(2) && iter->second.flags.test(6)) {
|
|
|
|
sendSize = UDPC_LSFULL_HEADER_SIZE + pInfo.dataSize;
|
2019-12-17 11:04:31 +00:00
|
|
|
buf = std::unique_ptr<char[]>(new char[sendSize]);
|
2019-11-18 08:37:03 +00:00
|
|
|
*((unsigned char*)(buf.get() + UDPC_MIN_HEADER_SIZE)) = 1;
|
|
|
|
} else {
|
|
|
|
sendSize = UDPC_NSFULL_HEADER_SIZE + pInfo.dataSize;
|
2019-12-17 11:04:31 +00:00
|
|
|
buf = std::unique_ptr<char[]>(new char[sendSize]);
|
2019-11-18 08:37:03 +00:00
|
|
|
*((unsigned char*)(buf.get() + UDPC_MIN_HEADER_SIZE)) = 0;
|
|
|
|
}
|
|
|
|
|
2019-08-18 09:34:45 +00:00
|
|
|
UDPC::preparePacket(
|
|
|
|
buf.get(),
|
2019-09-16 02:40:43 +00:00
|
|
|
protocolID,
|
2019-08-18 09:34:45 +00:00
|
|
|
iter->second.id,
|
|
|
|
iter->second.rseq,
|
|
|
|
iter->second.ack,
|
|
|
|
&iter->second.lseq,
|
2019-11-18 08:37:03 +00:00
|
|
|
(pInfo.flags & 0x4) | (isResending ? 0x8 : 0));
|
|
|
|
|
|
|
|
if(flags.test(2) && iter->second.flags.test(6)) {
|
|
|
|
#ifdef UDPC_LIBSODIUM_ENABLED
|
|
|
|
if(crypto_sign_detached(
|
|
|
|
(unsigned char*)(buf.get() + UDPC_MIN_HEADER_SIZE + 1), nullptr,
|
|
|
|
(unsigned char*)buf.get(), UDPC_MIN_HEADER_SIZE,
|
|
|
|
iter->second.sk) != 0) {
|
|
|
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
|
|
|
|
"Failed to sign packet for peer ",
|
|
|
|
UDPC_atostr((UDPC_HContext)this, iter->first.addr),
|
|
|
|
", port ",
|
|
|
|
iter->second.port);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
assert(!"libsodium disabled, invalid state");
|
|
|
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
|
|
|
|
"libsodium is disabled, cannot send packet");
|
|
|
|
continue;
|
|
|
|
#endif
|
|
|
|
std::memcpy(buf.get() + UDPC_LSFULL_HEADER_SIZE, pInfo.data, pInfo.dataSize);
|
|
|
|
} else {
|
|
|
|
std::memcpy(buf.get() + UDPC_NSFULL_HEADER_SIZE, pInfo.data, pInfo.dataSize);
|
|
|
|
}
|
|
|
|
|
2019-08-18 09:34:45 +00:00
|
|
|
|
2019-09-19 03:23:15 +00:00
|
|
|
UDPC_IPV6_SOCKADDR_TYPE destinationInfo;
|
2019-09-07 07:36:11 +00:00
|
|
|
destinationInfo.sin6_family = AF_INET6;
|
2019-09-20 05:01:26 +00:00
|
|
|
std::memcpy(
|
|
|
|
UDPC_IPV6_ADDR_SUB(destinationInfo.sin6_addr),
|
|
|
|
UDPC_IPV6_ADDR_SUB(iter->first.addr),
|
|
|
|
16);
|
2019-09-07 07:36:11 +00:00
|
|
|
destinationInfo.sin6_port = htons(iter->second.port);
|
2019-09-20 05:01:26 +00:00
|
|
|
destinationInfo.sin6_flowinfo = 0;
|
|
|
|
destinationInfo.sin6_scope_id = iter->first.scope_id;
|
2019-08-18 09:34:45 +00:00
|
|
|
long int sentBytes = sendto(
|
2019-09-16 02:40:43 +00:00
|
|
|
socketHandle,
|
2019-08-18 09:34:45 +00:00
|
|
|
buf.get(),
|
2019-11-18 08:37:03 +00:00
|
|
|
sendSize,
|
2019-08-18 09:34:45 +00:00
|
|
|
0,
|
|
|
|
(struct sockaddr*) &destinationInfo,
|
2019-09-19 03:23:15 +00:00
|
|
|
sizeof(UDPC_IPV6_SOCKADDR_TYPE));
|
2019-11-18 08:37:03 +00:00
|
|
|
if(sentBytes != sendSize) {
|
2019-09-20 05:26:59 +00:00
|
|
|
UDPC_CHECK_LOG(this,
|
2019-09-19 01:58:19 +00:00
|
|
|
UDPC_LoggingType::UDPC_ERROR,
|
2019-08-29 03:56:09 +00:00
|
|
|
"Failed to send packet to ",
|
2019-09-18 08:35:14 +00:00
|
|
|
UDPC_atostr((UDPC_HContext)this, iter->first.addr),
|
2019-09-17 11:33:47 +00:00
|
|
|
", port = ",
|
2019-08-29 03:56:09 +00:00
|
|
|
iter->second.port);
|
2019-08-28 06:54:18 +00:00
|
|
|
continue;
|
2019-08-18 09:34:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if((pInfo.flags & 0x4) == 0) {
|
|
|
|
// is check-received, store data in case packet gets lost
|
2019-09-07 07:36:11 +00:00
|
|
|
UDPC_PacketInfo sentPInfo = UDPC::get_empty_pinfo();
|
2019-11-18 08:37:03 +00:00
|
|
|
std::memcpy(sentPInfo.data, buf.get(), sendSize);
|
2019-08-18 09:34:45 +00:00
|
|
|
sentPInfo.flags = 0;
|
2019-11-18 08:37:03 +00:00
|
|
|
sentPInfo.dataSize = sendSize;
|
2019-09-07 07:36:11 +00:00
|
|
|
sentPInfo.sender.addr = in6addr_loopback;
|
2019-09-03 03:06:46 +00:00
|
|
|
sentPInfo.receiver.addr = iter->first.addr;
|
2019-09-23 11:11:12 +00:00
|
|
|
sentPInfo.sender.port = ntohs(socketInfo.sin6_port);
|
2019-09-03 03:06:46 +00:00
|
|
|
sentPInfo.receiver.port = iter->second.port;
|
2019-08-18 09:34:45 +00:00
|
|
|
|
2019-09-20 05:01:26 +00:00
|
|
|
iter->second.sentPkts.push_back(std::move(sentPInfo));
|
2019-08-22 11:16:07 +00:00
|
|
|
iter->second.cleanupSentPkts();
|
2019-08-18 09:34:45 +00:00
|
|
|
} else {
|
2019-08-22 11:16:07 +00:00
|
|
|
// is not check-received, only id stored in data array
|
2019-09-07 07:36:11 +00:00
|
|
|
UDPC_PacketInfo sentPInfo = UDPC::get_empty_pinfo();
|
2019-08-18 09:34:45 +00:00
|
|
|
sentPInfo.flags = 0x4;
|
|
|
|
sentPInfo.dataSize = 0;
|
2019-09-07 07:36:11 +00:00
|
|
|
sentPInfo.sender.addr = in6addr_loopback;
|
2019-09-03 03:06:46 +00:00
|
|
|
sentPInfo.receiver.addr = iter->first.addr;
|
2019-09-23 11:11:12 +00:00
|
|
|
sentPInfo.sender.port = ntohs(socketInfo.sin6_port);
|
2019-09-03 03:06:46 +00:00
|
|
|
sentPInfo.receiver.port = iter->second.port;
|
2019-09-20 05:01:26 +00:00
|
|
|
*((uint32_t*)(sentPInfo.data + 8)) = htonl(iter->second.lseq - 1);
|
2019-08-18 09:34:45 +00:00
|
|
|
|
2019-09-20 05:01:26 +00:00
|
|
|
iter->second.sentPkts.push_back(std::move(sentPInfo));
|
2019-08-22 11:16:07 +00:00
|
|
|
iter->second.cleanupSentPkts();
|
2019-08-18 09:34:45 +00:00
|
|
|
}
|
2019-08-22 11:16:07 +00:00
|
|
|
|
|
|
|
// store other pkt info
|
|
|
|
UDPC::SentPktInfo::Ptr sentPktInfo = std::make_shared<UDPC::SentPktInfo>();
|
|
|
|
sentPktInfo->id = iter->second.lseq - 1;
|
|
|
|
iter->second.sentInfoMap.insert(std::make_pair(sentPktInfo->id, sentPktInfo));
|
2019-07-21 05:29:31 +00:00
|
|
|
}
|
2019-09-20 05:01:26 +00:00
|
|
|
iter->second.sent = now;
|
2019-06-06 07:02:48 +00:00
|
|
|
}
|
|
|
|
|
2019-12-17 11:04:31 +00:00
|
|
|
// remove queued for deletion
|
|
|
|
for(auto delIter = deletionMap.begin(); delIter != deletionMap.end(); ++delIter) {
|
|
|
|
auto iter = conMap.find(*delIter);
|
|
|
|
if(iter != conMap.end()) {
|
|
|
|
if(iter->second.flags.test(4)) {
|
|
|
|
idMap.erase(iter->second.id);
|
|
|
|
}
|
|
|
|
auto addrConIter = addrConMap.find(delIter->addr);
|
|
|
|
if(addrConIter != addrConMap.end()) {
|
|
|
|
addrConIter->second.erase(*delIter);
|
|
|
|
if(addrConIter->second.empty()) {
|
|
|
|
addrConMap.erase(addrConIter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(isReceivingEvents.load()) {
|
|
|
|
externalEvents.push(UDPC_Event{
|
|
|
|
UDPC_ET_DISCONNECTED, iter->first, false});
|
|
|
|
}
|
|
|
|
conMap.erase(iter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
deletionMap.clear();
|
|
|
|
|
2019-08-18 10:14:14 +00:00
|
|
|
// receive packet
|
2019-09-19 03:23:15 +00:00
|
|
|
UDPC_IPV6_SOCKADDR_TYPE receivedData;
|
2019-08-18 10:14:14 +00:00
|
|
|
socklen_t receivedDataSize = sizeof(receivedData);
|
|
|
|
int bytes = recvfrom(
|
2019-09-16 02:40:43 +00:00
|
|
|
socketHandle,
|
|
|
|
recvBuf,
|
2019-08-18 10:14:14 +00:00
|
|
|
UDPC_PACKET_MAX_SIZE,
|
|
|
|
0,
|
|
|
|
(struct sockaddr*) &receivedData,
|
|
|
|
&receivedDataSize);
|
|
|
|
|
2019-09-19 03:23:15 +00:00
|
|
|
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
|
|
|
|
if(bytes == 0) {
|
|
|
|
// connection closed
|
|
|
|
return;
|
|
|
|
} else if(bytes == SOCKET_ERROR) {
|
|
|
|
int error = WSAGetLastError();
|
|
|
|
if(error != WSAEWOULDBLOCK) {
|
2019-09-20 05:26:59 +00:00
|
|
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
|
2019-09-19 03:23:15 +00:00
|
|
|
"Error receiving packet, ", error);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#else
|
2019-08-18 10:14:14 +00:00
|
|
|
if(bytes == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
|
|
|
|
// no packet was received
|
|
|
|
return;
|
2019-09-23 11:11:12 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
else if(bytes < UDPC_MIN_HEADER_SIZE) {
|
2019-08-18 10:14:14 +00:00
|
|
|
// packet size is too small, invalid packet
|
2019-09-20 05:26:59 +00:00
|
|
|
UDPC_CHECK_LOG(this,
|
2019-11-06 05:35:16 +00:00
|
|
|
UDPC_LoggingType::UDPC_VERBOSE,
|
2019-08-29 03:56:09 +00:00
|
|
|
"Received packet is smaller than header, ignoring packet from ",
|
2019-09-18 08:35:14 +00:00
|
|
|
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
|
2019-09-17 11:33:47 +00:00
|
|
|
", port = ",
|
2019-09-23 11:11:12 +00:00
|
|
|
ntohs(receivedData.sin6_port));
|
2019-08-18 10:14:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-09-16 02:40:43 +00:00
|
|
|
uint32_t temp = ntohl(*((uint32_t*)recvBuf));
|
|
|
|
if(temp != protocolID) {
|
2019-08-18 10:14:14 +00:00
|
|
|
// Invalid protocol id in packet
|
2019-09-20 05:26:59 +00:00
|
|
|
UDPC_CHECK_LOG(this,
|
2019-11-06 05:35:16 +00:00
|
|
|
UDPC_LoggingType::UDPC_VERBOSE,
|
2019-08-29 03:56:09 +00:00
|
|
|
"Received packet has invalid protocol id, ignoring packet from ",
|
2019-09-18 08:35:14 +00:00
|
|
|
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
|
2019-09-17 11:33:47 +00:00
|
|
|
", port = ",
|
|
|
|
ntohs(receivedData.sin6_port));
|
2019-08-18 10:14:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-09-16 02:40:43 +00:00
|
|
|
uint32_t conID = ntohl(*((uint32_t*)(recvBuf + 4)));
|
|
|
|
uint32_t seqID = ntohl(*((uint32_t*)(recvBuf + 8)));
|
|
|
|
uint32_t rseq = ntohl(*((uint32_t*)(recvBuf + 12)));
|
2019-09-17 11:33:47 +00:00
|
|
|
uint32_t ack = ntohl(*((uint32_t*)(recvBuf + 16)));
|
2019-08-18 10:14:14 +00:00
|
|
|
|
|
|
|
bool isConnect = conID & UDPC_ID_CONNECT;
|
|
|
|
bool isPing = conID & UDPC_ID_PING;
|
|
|
|
bool isNotRecChecked = conID & UDPC_ID_NO_REC_CHK;
|
|
|
|
bool isResending = conID & UDPC_ID_RESENDING;
|
|
|
|
conID &= 0x0FFFFFFF;
|
2019-12-18 05:34:53 +00:00
|
|
|
UDPC_ConnectionId identifier = UDPC_create_id_full(receivedData.sin6_addr,
|
|
|
|
receivedData.sin6_scope_id,
|
|
|
|
ntohs(receivedData.sin6_port));
|
2019-08-18 10:14:14 +00:00
|
|
|
|
2019-12-17 11:04:31 +00:00
|
|
|
if(isConnect && !isPing && bytes < (int)(UDPC_CON_HEADER_SIZE)) {
|
2019-09-23 11:11:12 +00:00
|
|
|
// invalid packet size
|
|
|
|
UDPC_CHECK_LOG(this,
|
2019-11-06 05:35:16 +00:00
|
|
|
UDPC_LoggingType::UDPC_VERBOSE,
|
2019-09-23 11:11:12 +00:00
|
|
|
"Got connect packet of invalid size from ",
|
|
|
|
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
|
|
|
|
", port = ",
|
|
|
|
ntohs(receivedData.sin6_port),
|
|
|
|
", ignoring");
|
|
|
|
return;
|
2019-12-17 11:04:31 +00:00
|
|
|
} else if ((!isConnect || (isConnect && isPing))
|
|
|
|
&& bytes < (int)UDPC_NSFULL_HEADER_SIZE) {
|
2019-09-23 11:11:12 +00:00
|
|
|
// packet is too small
|
|
|
|
UDPC_CHECK_LOG(this,
|
2019-11-06 05:35:16 +00:00
|
|
|
UDPC_LoggingType::UDPC_VERBOSE,
|
2019-09-23 11:11:12 +00:00
|
|
|
"Got non-connect packet of invalid size from ",
|
|
|
|
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
|
|
|
|
", port = ",
|
|
|
|
ntohs(receivedData.sin6_port),
|
|
|
|
", ignoring");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-11-18 08:37:03 +00:00
|
|
|
uint32_t pktType = 0;
|
2019-12-17 11:04:31 +00:00
|
|
|
if(isConnect && !isPing) {
|
2019-11-18 08:37:03 +00:00
|
|
|
pktType = ntohl(*((uint32_t*)(recvBuf + UDPC_MIN_HEADER_SIZE)));
|
|
|
|
switch(pktType) {
|
|
|
|
case 0: // client/server connect with libsodium disabled
|
|
|
|
break;
|
|
|
|
case 1: // client connect with libsodium enabled
|
|
|
|
break;
|
|
|
|
case 2: // server connect with libsodium enabled
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_WARNING,
|
|
|
|
"Got invalid connect pktType from ",
|
|
|
|
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
|
|
|
|
", port ", ntohs(receivedData.sin6_port));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
pktType = ((unsigned char*)recvBuf)[UDPC_MIN_HEADER_SIZE];
|
|
|
|
switch(pktType) {
|
|
|
|
case 0: // not signed
|
|
|
|
break;
|
|
|
|
case 1: // signed
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_WARNING,
|
|
|
|
"Got invalid pktType from ",
|
|
|
|
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
|
|
|
|
", port ", ntohs(receivedData.sin6_port));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-17 11:04:31 +00:00
|
|
|
if(isConnect && !isPing) {
|
2019-08-18 10:14:14 +00:00
|
|
|
// is connect packet and is accepting new connections
|
2019-09-16 02:40:43 +00:00
|
|
|
if(!flags.test(1)
|
2019-11-18 08:37:03 +00:00
|
|
|
&& conMap.find(identifier) == conMap.end()
|
|
|
|
&& isAcceptNewConnections.load()) {
|
2019-08-18 10:14:14 +00:00
|
|
|
// is receiving as server, connection did not already exist
|
2019-12-09 12:27:58 +00:00
|
|
|
int authPolicy = this->authPolicy.load();
|
|
|
|
if(pktType == 1 && !flags.test(2)
|
|
|
|
&& authPolicy == UDPC_AuthPolicy::UDPC_AUTH_POLICY_STRICT) {
|
|
|
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
|
|
|
|
"Client peer ",
|
|
|
|
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
|
|
|
|
" port ",
|
|
|
|
ntohs(receivedData.sin6_port),
|
|
|
|
" attempted connection with packet authentication "
|
|
|
|
"enabled, but auth is disabled and AuthPolicy is STRICT");
|
|
|
|
return;
|
|
|
|
} else if(pktType == 0 && flags.test(2)
|
|
|
|
&& authPolicy == UDPC_AuthPolicy::UDPC_AUTH_POLICY_STRICT) {
|
|
|
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
|
|
|
|
"Client peer ",
|
|
|
|
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
|
|
|
|
" port ",
|
|
|
|
ntohs(receivedData.sin6_port),
|
|
|
|
" attempted connection with packet authentication "
|
|
|
|
"disabled, but auth is enabled and AuthPolicy is STRICT");
|
|
|
|
return;
|
|
|
|
}
|
2019-11-19 11:55:20 +00:00
|
|
|
unsigned char *sk = nullptr;
|
|
|
|
unsigned char *pk = nullptr;
|
|
|
|
if(keysSet.load()) {
|
|
|
|
sk = this->sk;
|
|
|
|
pk = this->pk;
|
|
|
|
}
|
2019-11-18 08:37:03 +00:00
|
|
|
UDPC::ConnectionData newConnection(
|
|
|
|
true,
|
|
|
|
this,
|
|
|
|
receivedData.sin6_addr,
|
|
|
|
receivedData.sin6_scope_id,
|
|
|
|
ntohs(receivedData.sin6_port),
|
|
|
|
#ifdef UDPC_LIBSODIUM_ENABLED
|
2019-11-19 11:55:20 +00:00
|
|
|
pktType == 1 && flags.test(2),
|
|
|
|
sk, pk);
|
2019-11-18 08:37:03 +00:00
|
|
|
#else
|
2019-11-19 11:55:20 +00:00
|
|
|
false,
|
|
|
|
sk, pk);
|
2019-11-18 08:37:03 +00:00
|
|
|
#endif
|
2019-11-21 06:15:05 +00:00
|
|
|
|
2019-09-23 11:11:12 +00:00
|
|
|
if(newConnection.flags.test(5)) {
|
|
|
|
UDPC_CHECK_LOG(this,
|
|
|
|
UDPC_LoggingType::UDPC_ERROR,
|
|
|
|
"Failed to init ConnectionData instance (libsodium init "
|
|
|
|
"fail) while server establishing connection with ",
|
|
|
|
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
|
|
|
|
", port = ",
|
|
|
|
ntohs(receivedData.sin6_port));
|
|
|
|
return;
|
|
|
|
}
|
2019-11-18 08:37:03 +00:00
|
|
|
if(pktType == 1 && flags.test(2)) {
|
|
|
|
#ifdef UDPC_LIBSODIUM_ENABLED
|
2019-11-21 06:15:05 +00:00
|
|
|
# ifndef NDEBUG
|
|
|
|
if(willLog(UDPC_LoggingType::UDPC_DEBUG)) {
|
|
|
|
std::string verificationString(
|
|
|
|
recvBuf + UDPC_MIN_HEADER_SIZE + 4 + crypto_sign_PUBLICKEYBYTES + 4,
|
|
|
|
ntohl(*((uint32_t*)(recvBuf + UDPC_MIN_HEADER_SIZE + 4 + crypto_sign_PUBLICKEYBYTES))));
|
|
|
|
log_impl(UDPC_LoggingType::UDPC_DEBUG,
|
|
|
|
"Server got verification string \"",
|
|
|
|
verificationString, "\"");
|
|
|
|
}
|
|
|
|
# endif
|
2019-11-18 08:37:03 +00:00
|
|
|
std::memcpy(
|
|
|
|
newConnection.peer_pk,
|
|
|
|
recvBuf + UDPC_MIN_HEADER_SIZE + 4,
|
|
|
|
crypto_sign_PUBLICKEYBYTES);
|
2019-12-17 11:04:31 +00:00
|
|
|
newConnection.verifyMessage = std::unique_ptr<char[]>(new char[crypto_sign_BYTES]);
|
2019-11-18 08:37:03 +00:00
|
|
|
crypto_sign_detached(
|
|
|
|
(unsigned char*)newConnection.verifyMessage.get(),
|
|
|
|
nullptr,
|
|
|
|
(unsigned char*)(recvBuf + UDPC_MIN_HEADER_SIZE + 4 + crypto_sign_PUBLICKEYBYTES + 4),
|
2019-11-21 06:15:05 +00:00
|
|
|
ntohl(*((uint32_t*)(recvBuf + UDPC_MIN_HEADER_SIZE + 4 + crypto_sign_PUBLICKEYBYTES))),
|
|
|
|
newConnection.sk);
|
2019-11-18 08:37:03 +00:00
|
|
|
#else
|
|
|
|
assert(!"libsodium disabled, invalid state");
|
|
|
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
|
|
|
|
"libsodium is disabled, cannot process received packet");
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
}
|
2019-09-20 05:26:59 +00:00
|
|
|
UDPC_CHECK_LOG(this,
|
2019-11-06 05:35:16 +00:00
|
|
|
UDPC_LoggingType::UDPC_INFO,
|
2019-08-29 03:56:09 +00:00
|
|
|
"Establishing connection with client ",
|
2019-09-18 08:35:14 +00:00
|
|
|
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
|
2019-09-17 11:33:47 +00:00
|
|
|
", port = ",
|
|
|
|
ntohs(receivedData.sin6_port),
|
2019-11-18 08:37:03 +00:00
|
|
|
", giving client id = ", newConnection.id,
|
|
|
|
pktType == 1 && flags.test(2) ?
|
|
|
|
", libsodium enabled" : ", libsodium disabled");
|
2019-08-22 07:08:05 +00:00
|
|
|
|
2019-09-16 02:40:43 +00:00
|
|
|
idMap.insert(std::make_pair(newConnection.id, identifier));
|
|
|
|
conMap.insert(std::make_pair(identifier, std::move(newConnection)));
|
|
|
|
auto addrConIter = addrConMap.find(identifier.addr);
|
|
|
|
if(addrConIter == addrConMap.end()) {
|
|
|
|
auto insertResult = addrConMap.insert(
|
2019-08-28 07:38:14 +00:00
|
|
|
std::make_pair(
|
2019-09-03 03:06:46 +00:00
|
|
|
identifier.addr,
|
|
|
|
std::unordered_set<UDPC_ConnectionId, UDPC::ConnectionIdHasher>{}
|
2019-08-28 07:38:14 +00:00
|
|
|
));
|
|
|
|
assert(insertResult.second
|
|
|
|
&& "Must successfully insert into addrConMap");
|
|
|
|
addrConIter = insertResult.first;
|
|
|
|
}
|
|
|
|
addrConIter->second.insert(identifier);
|
2019-11-11 07:08:51 +00:00
|
|
|
if(isReceivingEvents.load()) {
|
|
|
|
externalEvents.push(UDPC_Event{
|
|
|
|
UDPC_ET_CONNECTED,
|
|
|
|
identifier,
|
|
|
|
false});
|
|
|
|
}
|
2019-09-16 02:40:43 +00:00
|
|
|
} else if (flags.test(1)) {
|
2019-08-22 07:08:05 +00:00
|
|
|
// is client
|
2019-09-16 02:40:43 +00:00
|
|
|
auto iter = conMap.find(identifier);
|
|
|
|
if(iter == conMap.end() || !iter->second.flags.test(3)) {
|
2019-11-18 08:37:03 +00:00
|
|
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_DEBUG,
|
|
|
|
"client dropped pkt from ",
|
|
|
|
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
|
|
|
|
", port ", ntohs(receivedData.sin6_port));
|
|
|
|
return;
|
|
|
|
}
|
2019-12-09 12:27:58 +00:00
|
|
|
int authPolicy = this->authPolicy.load();
|
|
|
|
if(pktType == 2 && !iter->second.flags.test(6)
|
|
|
|
&& authPolicy == UDPC_AuthPolicy::UDPC_AUTH_POLICY_STRICT) {
|
|
|
|
// This block actually should never happen, because the server
|
|
|
|
// receives a packet first. If client requests without auth,
|
|
|
|
// then the server will either deny connection (if strict) or
|
|
|
|
// fallback to a connection without auth (if fallback).
|
|
|
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
|
|
|
|
"Server peer ",
|
|
|
|
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
|
|
|
|
" port ",
|
|
|
|
ntohs(receivedData.sin6_port),
|
|
|
|
" attempted connection with packet authentication "
|
|
|
|
"enabled, but auth is disabled and AuthPolicy is STRICT");
|
|
|
|
return;
|
|
|
|
} else if(pktType == 0 && iter->second.flags.test(6)
|
|
|
|
&& authPolicy == UDPC_AuthPolicy::UDPC_AUTH_POLICY_STRICT) {
|
|
|
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
|
|
|
|
"Server peer ",
|
|
|
|
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
|
|
|
|
" port ",
|
|
|
|
ntohs(receivedData.sin6_port),
|
|
|
|
" attempted connection with packet authentication "
|
|
|
|
"disabled, but auth is enabled and AuthPolicy is STRICT");
|
|
|
|
return;
|
|
|
|
}
|
2019-11-18 08:37:03 +00:00
|
|
|
|
|
|
|
if(pktType == 2 && flags.test(2) && iter->second.flags.test(6)) {
|
|
|
|
#ifdef UDPC_LIBSODIUM_ENABLED
|
2019-11-19 11:55:20 +00:00
|
|
|
if(iter->second.flags.test(7)) {
|
|
|
|
if(std::memcmp(iter->second.peer_pk,
|
|
|
|
recvBuf + UDPC_MIN_HEADER_SIZE + 4,
|
|
|
|
crypto_sign_PUBLICKEYBYTES) != 0) {
|
|
|
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_WARNING,
|
|
|
|
"peer_pk did not match pre-set peer_pk, not "
|
|
|
|
"establishing connection");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
std::memcpy(iter->second.peer_pk,
|
|
|
|
recvBuf + UDPC_MIN_HEADER_SIZE + 4,
|
|
|
|
crypto_sign_PUBLICKEYBYTES);
|
|
|
|
}
|
2019-11-18 08:37:03 +00:00
|
|
|
if(crypto_sign_verify_detached(
|
|
|
|
(unsigned char*)(recvBuf + UDPC_MIN_HEADER_SIZE + 4 + crypto_sign_PUBLICKEYBYTES),
|
|
|
|
(unsigned char*)(iter->second.verifyMessage.get() + 4),
|
|
|
|
*((uint32_t*)(iter->second.verifyMessage.get())),
|
|
|
|
iter->second.peer_pk) != 0) {
|
|
|
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_WARNING,
|
|
|
|
"Failed to verify peer (server) ",
|
|
|
|
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
|
|
|
|
", port = ",
|
|
|
|
ntohs(receivedData.sin6_port));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
assert(!"libsodium disabled, invalid state");
|
|
|
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
|
|
|
|
"libsodium is disabled, cannot process received packet");
|
2019-08-22 07:08:05 +00:00
|
|
|
return;
|
2019-11-18 08:37:03 +00:00
|
|
|
#endif
|
|
|
|
} else if(pktType == 0 && iter->second.flags.test(6)) {
|
|
|
|
iter->second.flags.reset(6);
|
2019-11-19 11:55:20 +00:00
|
|
|
if(iter->second.flags.test(7)) {
|
|
|
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_WARNING,
|
|
|
|
"peer is not using libsodium, but peer_pk was "
|
|
|
|
"pre-set, dropping to no-verification mode");
|
|
|
|
}
|
2019-08-22 07:08:05 +00:00
|
|
|
}
|
2019-11-18 08:37:03 +00:00
|
|
|
|
2019-08-22 07:08:05 +00:00
|
|
|
iter->second.flags.reset(3);
|
|
|
|
iter->second.id = conID;
|
|
|
|
iter->second.flags.set(4);
|
2019-11-18 08:37:03 +00:00
|
|
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_INFO,
|
2019-08-29 03:56:09 +00:00
|
|
|
"Established connection with server ",
|
2019-09-18 08:35:14 +00:00
|
|
|
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
|
2019-09-17 11:33:47 +00:00
|
|
|
", port = ",
|
|
|
|
ntohs(receivedData.sin6_port),
|
2019-11-18 08:37:03 +00:00
|
|
|
", got id = ", conID,
|
|
|
|
flags.test(2) && iter->second.flags.test(6) ?
|
|
|
|
", libsodium enabled" : ", libsodium disabled");
|
2019-11-11 07:08:51 +00:00
|
|
|
if(isReceivingEvents.load()) {
|
|
|
|
externalEvents.push(UDPC_Event{
|
|
|
|
UDPC_ET_CONNECTED,
|
|
|
|
identifier,
|
|
|
|
false});
|
|
|
|
}
|
2019-08-18 10:14:14 +00:00
|
|
|
}
|
2019-08-22 07:08:05 +00:00
|
|
|
return;
|
2019-08-18 10:14:14 +00:00
|
|
|
}
|
2019-08-18 09:34:45 +00:00
|
|
|
|
2019-09-16 02:40:43 +00:00
|
|
|
auto iter = conMap.find(identifier);
|
|
|
|
if(iter == conMap.end() || iter->second.flags.test(3)
|
2019-08-22 07:08:05 +00:00
|
|
|
|| !iter->second.flags.test(4) || iter->second.id != conID) {
|
|
|
|
return;
|
2019-12-17 11:04:31 +00:00
|
|
|
} else if(isPing && !isConnect) {
|
2019-08-22 07:08:05 +00:00
|
|
|
iter->second.flags.set(0);
|
|
|
|
}
|
|
|
|
|
2019-11-18 08:37:03 +00:00
|
|
|
if(pktType == 1) {
|
|
|
|
#ifdef UDPC_LIBSODIUM_ENABLED
|
|
|
|
// verify signature of header
|
|
|
|
if(crypto_sign_verify_detached(
|
|
|
|
(unsigned char*)(recvBuf + UDPC_MIN_HEADER_SIZE + 1),
|
|
|
|
(unsigned char*)recvBuf,
|
|
|
|
UDPC_MIN_HEADER_SIZE,
|
|
|
|
iter->second.peer_pk) != 0) {
|
|
|
|
UDPC_CHECK_LOG(
|
|
|
|
this,
|
|
|
|
UDPC_LoggingType::UDPC_INFO,
|
|
|
|
"Failed to verify received packet from",
|
|
|
|
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
|
|
|
|
", port = ",
|
|
|
|
ntohs(receivedData.sin6_port),
|
|
|
|
", ignoring");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
assert(!"libsodium disabled, invalid state");
|
|
|
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
|
|
|
|
"libsodium is disabled, cannot process received packet");
|
2019-09-23 11:11:12 +00:00
|
|
|
return;
|
2019-11-18 08:37:03 +00:00
|
|
|
#endif
|
2019-09-23 11:11:12 +00:00
|
|
|
}
|
|
|
|
|
2019-08-22 07:08:05 +00:00
|
|
|
// packet is valid
|
2019-09-20 05:26:59 +00:00
|
|
|
UDPC_CHECK_LOG(this,
|
2019-11-06 05:35:16 +00:00
|
|
|
UDPC_LoggingType::UDPC_VERBOSE,
|
2019-08-29 03:56:09 +00:00
|
|
|
"Received valid packet from ",
|
2019-09-18 08:35:14 +00:00
|
|
|
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
|
2019-09-17 11:33:47 +00:00
|
|
|
", port = ",
|
|
|
|
ntohs(receivedData.sin6_port),
|
|
|
|
", packet id = ", seqID,
|
|
|
|
", good mode = ", iter->second.flags.test(1) ? "yes" : "no",
|
2019-12-17 11:58:44 +00:00
|
|
|
isPing && !isConnect ? ", ping"
|
|
|
|
: (isPing && isConnect ? ", disc" : ""));
|
2019-08-22 07:08:05 +00:00
|
|
|
|
2019-12-17 11:04:31 +00:00
|
|
|
// check if is delete
|
|
|
|
if(isConnect && isPing) {
|
|
|
|
auto conIter = conMap.find(identifier);
|
|
|
|
if(conIter != conMap.end()) {
|
|
|
|
UDPC_CHECK_LOG(this,
|
|
|
|
UDPC_LoggingType::UDPC_VERBOSE,
|
|
|
|
"Packet is request-disconnect packet, deleting connection...");
|
|
|
|
if(conIter->second.flags.test(4)) {
|
|
|
|
idMap.erase(conIter->second.id);
|
|
|
|
}
|
|
|
|
auto addrConIter = addrConMap.find(identifier.addr);
|
|
|
|
if(addrConIter != addrConMap.end()) {
|
|
|
|
addrConIter->second.erase(identifier);
|
|
|
|
if(addrConIter->second.empty()) {
|
|
|
|
addrConMap.erase(addrConIter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(isReceivingEvents.load()) {
|
|
|
|
externalEvents.push(UDPC_Event{
|
|
|
|
UDPC_ET_DISCONNECTED, identifier, false});
|
|
|
|
}
|
|
|
|
conMap.erase(conIter);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-22 11:16:07 +00:00
|
|
|
// update rtt
|
|
|
|
for(auto sentIter = iter->second.sentPkts.rbegin(); sentIter != iter->second.sentPkts.rend(); ++sentIter) {
|
2019-08-27 03:42:43 +00:00
|
|
|
uint32_t id = ntohl(*((uint32_t*)(sentIter->data + 8)));
|
2019-08-22 11:16:07 +00:00
|
|
|
if(id == rseq) {
|
|
|
|
auto sentInfoIter = iter->second.sentInfoMap.find(id);
|
|
|
|
assert(sentInfoIter != iter->second.sentInfoMap.end()
|
|
|
|
&& "sentInfoMap should have known stored id");
|
2019-08-27 07:31:24 +00:00
|
|
|
auto diff = now - sentInfoIter->second->sentTime;
|
2019-08-22 11:16:07 +00:00
|
|
|
if(diff > iter->second.rtt) {
|
2019-08-27 07:31:24 +00:00
|
|
|
iter->second.rtt += (diff - iter->second.rtt) / 10;
|
2019-08-22 11:16:07 +00:00
|
|
|
} else {
|
2019-08-27 07:31:24 +00:00
|
|
|
iter->second.rtt -= (iter->second.rtt - diff) / 10;
|
2019-08-22 11:16:07 +00:00
|
|
|
}
|
|
|
|
|
2019-08-27 07:31:24 +00:00
|
|
|
iter->second.flags.set(2, iter->second.rtt <= UDPC::GOOD_RTT_LIMIT);
|
2019-08-22 11:16:07 +00:00
|
|
|
|
2019-09-20 05:26:59 +00:00
|
|
|
UDPC_CHECK_LOG(this,
|
2019-11-06 05:35:16 +00:00
|
|
|
UDPC_LoggingType::UDPC_VERBOSE,
|
2019-08-29 03:56:09 +00:00
|
|
|
"RTT: ",
|
2019-09-17 11:33:47 +00:00
|
|
|
UDPC::durationToFSec(iter->second.rtt) * 1000.0f,
|
|
|
|
" milliseconds");
|
2019-08-22 11:16:07 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
iter->second.received = now;
|
2019-08-27 03:42:43 +00:00
|
|
|
|
|
|
|
// check pkt timeout
|
|
|
|
--rseq;
|
|
|
|
for(; ack != 0; ack = ack << 1) {
|
|
|
|
if((ack & 0x80000000) != 0) {
|
|
|
|
--rseq;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// pkt not received yet, find it in sent to check if it timed out
|
|
|
|
for(auto sentIter = iter->second.sentPkts.rbegin(); sentIter != iter->second.sentPkts.rend(); ++sentIter) {
|
|
|
|
uint32_t sentID = ntohl(*((uint32_t*)(sentIter->data + 8)));
|
|
|
|
if(sentID == rseq) {
|
|
|
|
if((sentIter->flags & 0x4) != 0 || (sentIter->flags & 0x8) != 0) {
|
|
|
|
// already resent or not rec-checked pkt
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
auto sentInfoIter = iter->second.sentInfoMap.find(sentID);
|
|
|
|
assert(sentInfoIter != iter->second.sentInfoMap.end()
|
|
|
|
&& "Every entry in sentPkts must have a corresponding entry in sentInfoMap");
|
2019-08-27 07:31:24 +00:00
|
|
|
auto duration = now - sentInfoIter->second->sentTime;
|
|
|
|
if(duration > UDPC::PACKET_TIMEOUT_TIME) {
|
2019-11-18 08:37:03 +00:00
|
|
|
bool pktSigned = sentIter->data[UDPC_MIN_HEADER_SIZE] == 1;
|
|
|
|
if((pktSigned && sentIter->dataSize <= UDPC_LSFULL_HEADER_SIZE)
|
|
|
|
|| (!pktSigned && sentIter->dataSize <= UDPC_NSFULL_HEADER_SIZE)) {
|
2019-09-20 05:26:59 +00:00
|
|
|
UDPC_CHECK_LOG(this,
|
2019-11-06 05:35:16 +00:00
|
|
|
UDPC_LoggingType::UDPC_VERBOSE,
|
2019-08-29 03:56:09 +00:00
|
|
|
"Timed out packet has no payload (probably "
|
|
|
|
"heartbeat packet), ignoring it");
|
2019-08-27 03:42:43 +00:00
|
|
|
sentIter->flags |= 0x8;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2019-09-07 07:36:11 +00:00
|
|
|
UDPC_PacketInfo resendingData = UDPC::get_empty_pinfo();
|
2019-11-18 08:37:03 +00:00
|
|
|
if(pktSigned) {
|
|
|
|
resendingData.dataSize = sentIter->dataSize - UDPC_LSFULL_HEADER_SIZE;
|
|
|
|
std::memcpy(resendingData.data,
|
|
|
|
sentIter->data + UDPC_LSFULL_HEADER_SIZE,
|
|
|
|
resendingData.dataSize);
|
|
|
|
} else {
|
|
|
|
resendingData.dataSize = sentIter->dataSize - UDPC_NSFULL_HEADER_SIZE;
|
|
|
|
std::memcpy(resendingData.data,
|
|
|
|
sentIter->data + UDPC_NSFULL_HEADER_SIZE,
|
|
|
|
resendingData.dataSize);
|
|
|
|
}
|
2019-08-27 03:42:43 +00:00
|
|
|
resendingData.flags = 0;
|
2019-09-27 11:19:48 +00:00
|
|
|
iter->second.priorityPkts.push_back(resendingData);
|
2019-08-27 03:42:43 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
--rseq;
|
|
|
|
}
|
2019-08-22 11:16:07 +00:00
|
|
|
|
2019-08-27 04:03:38 +00:00
|
|
|
// calculate sequence and ack
|
|
|
|
bool isOutOfOrder = false;
|
|
|
|
uint32_t diff = 0;
|
|
|
|
if(seqID > iter->second.rseq) {
|
|
|
|
diff = seqID - iter->second.rseq;
|
|
|
|
if(diff <= 0x7FFFFFFF) {
|
|
|
|
// sequence is more recent
|
|
|
|
iter->second.rseq = seqID;
|
|
|
|
iter->second.ack = (iter->second.ack >> diff) | 0x80000000;
|
|
|
|
} else {
|
|
|
|
// sequence is older, recalc diff
|
|
|
|
diff = 0xFFFFFFFF - seqID + 1 + iter->second.rseq;
|
|
|
|
if((iter->second.ack & (0x80000000 >> (diff - 1))) != 0) {
|
|
|
|
// already received packet
|
2019-09-20 05:26:59 +00:00
|
|
|
UDPC_CHECK_LOG(this,
|
2019-11-06 05:35:16 +00:00
|
|
|
UDPC_LoggingType::UDPC_VERBOSE,
|
2019-08-29 03:56:09 +00:00
|
|
|
"Received packet is already marked as received, ignoring it");
|
2019-08-27 04:03:38 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
iter->second.ack |= 0x80000000 >> (diff - 1);
|
|
|
|
isOutOfOrder = true;
|
|
|
|
}
|
|
|
|
} else if(seqID < iter->second.rseq) {
|
|
|
|
diff = iter->second.rseq - seqID;
|
|
|
|
if(diff <= 0x7FFFFFFF) {
|
|
|
|
// sequence is older
|
|
|
|
if((iter->second.ack & (0x80000000 >> (diff - 1))) != 0) {
|
|
|
|
// already received packet
|
2019-09-20 05:26:59 +00:00
|
|
|
UDPC_CHECK_LOG(this,
|
2019-11-06 05:35:16 +00:00
|
|
|
UDPC_LoggingType::UDPC_VERBOSE,
|
2019-08-29 03:56:09 +00:00
|
|
|
"Received packet is already marked as received, ignoring it");
|
2019-08-27 04:03:38 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
iter->second.ack |= 0x80000000 >> (diff - 1);
|
|
|
|
isOutOfOrder = true;
|
|
|
|
} else {
|
|
|
|
// sequence is more recent, recalc diff
|
|
|
|
diff = 0xFFFFFFFF - iter->second.rseq + 1 + seqID;
|
|
|
|
iter->second.rseq = seqID;
|
|
|
|
iter->second.ack = (iter->second.ack >> diff) | 0x80000000;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// already received packet
|
2019-09-20 05:26:59 +00:00
|
|
|
UDPC_CHECK_LOG(this,
|
2019-11-06 05:35:16 +00:00
|
|
|
UDPC_LoggingType::UDPC_VERBOSE,
|
2019-08-29 03:56:09 +00:00
|
|
|
"Received packet is already marked as received, ignoring it");
|
2019-08-27 04:03:38 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-08-29 03:56:09 +00:00
|
|
|
if(isOutOfOrder) {
|
2019-09-20 05:26:59 +00:00
|
|
|
UDPC_CHECK_LOG(this,
|
2019-11-06 05:35:16 +00:00
|
|
|
UDPC_LoggingType::UDPC_INFO,
|
2019-08-29 03:56:09 +00:00
|
|
|
"Received packet is out of order");
|
|
|
|
}
|
2019-08-27 04:03:38 +00:00
|
|
|
|
2019-12-27 04:35:28 +00:00
|
|
|
if(pktType == 0 && bytes > (int)UDPC_NSFULL_HEADER_SIZE) {
|
2019-09-07 07:36:11 +00:00
|
|
|
UDPC_PacketInfo recPktInfo = UDPC::get_empty_pinfo();
|
2019-12-27 04:35:28 +00:00
|
|
|
recPktInfo.dataSize = bytes - UDPC_NSFULL_HEADER_SIZE;
|
2019-12-30 05:13:38 +00:00
|
|
|
std::memcpy(recPktInfo.data,
|
|
|
|
recvBuf + UDPC_NSFULL_HEADER_SIZE,
|
|
|
|
recPktInfo.dataSize);
|
2019-08-27 04:03:38 +00:00
|
|
|
recPktInfo.flags =
|
|
|
|
(isConnect ? 0x1 : 0)
|
|
|
|
| (isPing ? 0x2 : 0)
|
|
|
|
| (isNotRecChecked ? 0x4 : 0)
|
|
|
|
| (isResending ? 0x8 : 0);
|
2019-09-07 07:36:11 +00:00
|
|
|
recPktInfo.sender.addr = receivedData.sin6_addr;
|
|
|
|
recPktInfo.receiver.addr = in6addr_loopback;
|
2019-09-17 11:33:47 +00:00
|
|
|
recPktInfo.sender.port = ntohs(receivedData.sin6_port);
|
|
|
|
recPktInfo.receiver.port = ntohs(socketInfo.sin6_port);
|
2019-12-27 04:35:28 +00:00
|
|
|
recPktInfo.rtt = durationToMS(iter->second.rtt);
|
|
|
|
|
|
|
|
receivedPkts.push(recPktInfo);
|
|
|
|
} else if(pktType == 1 && bytes > (int)UDPC_LSFULL_HEADER_SIZE) {
|
|
|
|
UDPC_PacketInfo recPktInfo = UDPC::get_empty_pinfo();
|
|
|
|
recPktInfo.dataSize = bytes - UDPC_LSFULL_HEADER_SIZE;
|
2019-12-30 05:13:38 +00:00
|
|
|
std::memcpy(recPktInfo.data,
|
|
|
|
recvBuf + UDPC_LSFULL_HEADER_SIZE,
|
|
|
|
recPktInfo.dataSize);
|
2019-12-27 04:35:28 +00:00
|
|
|
recPktInfo.flags =
|
|
|
|
(isConnect ? 0x1 : 0)
|
|
|
|
| (isPing ? 0x2 : 0)
|
|
|
|
| (isNotRecChecked ? 0x4 : 0)
|
|
|
|
| (isResending ? 0x8 : 0);
|
|
|
|
recPktInfo.sender.addr = receivedData.sin6_addr;
|
|
|
|
recPktInfo.receiver.addr = in6addr_loopback;
|
|
|
|
recPktInfo.sender.port = ntohs(receivedData.sin6_port);
|
|
|
|
recPktInfo.receiver.port = ntohs(socketInfo.sin6_port);
|
|
|
|
recPktInfo.rtt = durationToMS(iter->second.rtt);
|
2019-08-27 04:03:38 +00:00
|
|
|
|
2019-11-06 05:35:16 +00:00
|
|
|
receivedPkts.push(recPktInfo);
|
2019-11-18 08:37:03 +00:00
|
|
|
} else {
|
2019-09-20 05:26:59 +00:00
|
|
|
UDPC_CHECK_LOG(this,
|
2019-09-19 01:58:19 +00:00
|
|
|
UDPC_LoggingType::UDPC_VERBOSE,
|
2019-09-18 02:42:16 +00:00
|
|
|
"Received packet has no payload (probably heartbeat packet)");
|
2019-08-27 04:03:38 +00:00
|
|
|
}
|
2019-06-06 07:02:48 +00:00
|
|
|
}
|
|
|
|
|
2019-09-16 02:40:43 +00:00
|
|
|
UDPC::Context *UDPC::verifyContext(UDPC_HContext ctx) {
|
|
|
|
if(ctx == nullptr) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
UDPC::Context *c = (UDPC::Context *)ctx;
|
|
|
|
if(c->_contextIdentifier == UDPC_CONTEXT_IDENTIFIER) {
|
|
|
|
return c;
|
|
|
|
} else {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool UDPC::isBigEndian() {
|
2019-12-11 11:00:48 +00:00
|
|
|
/*
|
|
|
|
* 0 - unset
|
|
|
|
* 1 - is big endian
|
|
|
|
* 2 - is not big endian
|
|
|
|
*/
|
|
|
|
static char isBigEndian = 0;
|
|
|
|
if(isBigEndian != 0) {
|
|
|
|
return isBigEndian == 1;
|
2019-09-16 02:40:43 +00:00
|
|
|
}
|
|
|
|
union {
|
|
|
|
uint32_t i;
|
|
|
|
char c[4];
|
|
|
|
} bint = {0x01020304};
|
|
|
|
|
2019-12-11 11:00:48 +00:00
|
|
|
isBigEndian = (bint.c[0] == 1 ? 1 : 2);
|
|
|
|
return isBigEndian;
|
2019-09-16 02:40:43 +00:00
|
|
|
}
|
|
|
|
|
2019-09-23 11:11:12 +00:00
|
|
|
void UDPC::preparePacket(
|
|
|
|
char *data, uint32_t protocolID, uint32_t conID, uint32_t rseq,
|
2019-11-18 08:37:03 +00:00
|
|
|
uint32_t ack, uint32_t *seqID, int flags) {
|
2019-09-16 02:40:43 +00:00
|
|
|
uint32_t temp;
|
|
|
|
|
|
|
|
temp = htonl(protocolID);
|
|
|
|
std::memcpy(data, &temp, 4);
|
|
|
|
temp = htonl(conID | ((flags & 0x1) != 0 ? UDPC_ID_CONNECT : 0) |
|
|
|
|
((flags & 0x2) != 0 ? UDPC_ID_PING : 0) |
|
|
|
|
((flags & 0x4) != 0 ? UDPC_ID_NO_REC_CHK : 0) |
|
|
|
|
((flags & 0x8) != 0 ? UDPC_ID_RESENDING : 0));
|
|
|
|
std::memcpy(data + 4, &temp, 4);
|
|
|
|
|
|
|
|
if(seqID) {
|
|
|
|
temp = htonl(*seqID);
|
|
|
|
++(*seqID);
|
|
|
|
} else {
|
|
|
|
temp = 0;
|
|
|
|
}
|
|
|
|
std::memcpy(data + 8, &temp, 4);
|
|
|
|
|
|
|
|
temp = htonl(rseq);
|
|
|
|
std::memcpy(data + 12, &temp, 4);
|
|
|
|
temp = htonl(ack);
|
|
|
|
std::memcpy(data + 16, &temp, 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t UDPC::generateConnectionID(Context &ctx) {
|
2019-09-17 11:33:47 +00:00
|
|
|
auto dist = std::uniform_int_distribution<uint32_t>(0, 0x0FFFFFFF);
|
2019-09-16 02:40:43 +00:00
|
|
|
uint32_t id = dist(ctx.rng_engine);
|
|
|
|
while(ctx.idMap.find(id) != ctx.idMap.end()) {
|
|
|
|
id = dist(ctx.rng_engine);
|
|
|
|
}
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
|
|
|
float UDPC::durationToFSec(const std::chrono::steady_clock::duration& duration) {
|
|
|
|
return (float)duration.count()
|
|
|
|
* (float)std::decay_t<decltype(duration)>::period::num
|
|
|
|
/ (float)std::decay_t<decltype(duration)>::period::den;
|
|
|
|
}
|
|
|
|
|
2019-12-27 04:35:28 +00:00
|
|
|
uint16_t UDPC::durationToMS(const std::chrono::steady_clock::duration& duration) {
|
|
|
|
return std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
|
|
|
|
}
|
|
|
|
|
2019-09-16 02:40:43 +00:00
|
|
|
float UDPC::timePointsToFSec(
|
|
|
|
const std::chrono::steady_clock::time_point& older,
|
|
|
|
const std::chrono::steady_clock::time_point& newer) {
|
|
|
|
const auto dt = newer - older;
|
|
|
|
return (float)dt.count()
|
|
|
|
* (float)decltype(dt)::period::num / (float)decltype(dt)::period::den;
|
|
|
|
}
|
|
|
|
|
|
|
|
UDPC_PacketInfo UDPC::get_empty_pinfo() {
|
|
|
|
return UDPC_PacketInfo {
|
|
|
|
{0}, // data (array)
|
|
|
|
0, // flags
|
|
|
|
0, // dataSize
|
2019-12-27 04:35:28 +00:00
|
|
|
0, // rtt
|
2019-09-16 02:40:43 +00:00
|
|
|
{ // sender
|
|
|
|
{0}, // ipv6 addr
|
2019-09-18 08:35:14 +00:00
|
|
|
0, // scope_id
|
2019-09-16 02:40:43 +00:00
|
|
|
0 // port
|
|
|
|
},
|
|
|
|
{ // receiver
|
|
|
|
{0}, // ipv6 addr
|
2019-09-18 08:35:14 +00:00
|
|
|
0, // scope_id
|
2019-09-16 02:40:43 +00:00
|
|
|
0 // port
|
|
|
|
},
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
void UDPC::threadedUpdate(Context *ctx) {
|
|
|
|
auto now = std::chrono::steady_clock::now();
|
|
|
|
decltype(now) nextNow;
|
|
|
|
while(ctx->threadRunning.load()) {
|
|
|
|
now = std::chrono::steady_clock::now();
|
2019-12-19 02:39:34 +00:00
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> lock(ctx->mutex);
|
|
|
|
ctx->update_impl();
|
|
|
|
}
|
2019-09-16 02:40:43 +00:00
|
|
|
nextNow = std::chrono::steady_clock::now();
|
2019-11-13 05:06:48 +00:00
|
|
|
std::this_thread::sleep_for(ctx->threadedSleepTime - (nextNow - now));
|
2019-09-16 02:40:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-19 03:23:15 +00:00
|
|
|
UDPC_ConnectionId UDPC_create_id(UDPC_IPV6_ADDR_TYPE addr, uint16_t port) {
|
2019-12-18 05:20:29 +00:00
|
|
|
UDPC_ConnectionId result;
|
|
|
|
|
|
|
|
std::memset(&result, 0, sizeof(UDPC_ConnectionId));
|
|
|
|
|
|
|
|
result.addr = addr;
|
|
|
|
// result.scope_id = 0;
|
|
|
|
result.port = port;
|
|
|
|
return result;
|
2019-09-18 08:35:14 +00:00
|
|
|
}
|
|
|
|
|
2019-09-19 03:23:15 +00:00
|
|
|
UDPC_ConnectionId UDPC_create_id_full(UDPC_IPV6_ADDR_TYPE addr, uint32_t scope_id, uint16_t port) {
|
2019-12-18 05:20:29 +00:00
|
|
|
UDPC_ConnectionId result;
|
|
|
|
|
|
|
|
std::memset(&result, 0, sizeof(UDPC_ConnectionId));
|
|
|
|
|
|
|
|
result.addr = addr;
|
|
|
|
result.scope_id = scope_id;
|
|
|
|
result.port = port;
|
|
|
|
return result;
|
2019-09-16 02:40:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
UDPC_ConnectionId UDPC_create_id_anyaddr(uint16_t port) {
|
2019-12-18 05:20:29 +00:00
|
|
|
UDPC_ConnectionId result;
|
|
|
|
|
|
|
|
std::memset(&result, 0, sizeof(UDPC_ConnectionId));
|
|
|
|
|
|
|
|
// result.addr = in6addr_any;
|
|
|
|
result.scope_id = 0;
|
|
|
|
result.port = port;
|
|
|
|
return result;
|
2019-09-16 02:40:43 +00:00
|
|
|
}
|
|
|
|
|
2019-11-13 03:15:12 +00:00
|
|
|
UDPC_ConnectionId UDPC_create_id_easy(const char *addrString, uint16_t port) {
|
2019-12-18 05:20:29 +00:00
|
|
|
UDPC_ConnectionId result;
|
|
|
|
|
|
|
|
std::memset(&result, 0, sizeof(UDPC_ConnectionId));
|
|
|
|
|
|
|
|
result.port = port;
|
|
|
|
|
2019-12-17 03:52:10 +00:00
|
|
|
if(std::regex_match(addrString, ipv6_regex_nolink)
|
|
|
|
|| std::regex_match(addrString, ipv4_regex)) {
|
2019-12-18 05:20:29 +00:00
|
|
|
result.addr = UDPC_strtoa(addrString);
|
2019-11-13 03:15:12 +00:00
|
|
|
} else if(std::regex_match(addrString, ipv6_regex_linkonly)) {
|
2019-12-18 05:20:29 +00:00
|
|
|
result.addr = UDPC_strtoa_link(addrString, &result.scope_id);
|
2019-11-13 03:15:12 +00:00
|
|
|
} else {
|
2019-12-18 05:20:29 +00:00
|
|
|
result.addr = in6addr_loopback;
|
2019-11-13 03:15:12 +00:00
|
|
|
}
|
2019-12-18 05:20:29 +00:00
|
|
|
return result;
|
2019-11-13 03:15:12 +00:00
|
|
|
}
|
|
|
|
|
2019-11-18 08:37:03 +00:00
|
|
|
UDPC_HContext UDPC_init(UDPC_ConnectionId listenId, int isClient, int isUsingLibsodium) {
|
2019-09-16 02:40:43 +00:00
|
|
|
UDPC::Context *ctx = new UDPC::Context(false);
|
2019-09-17 11:33:47 +00:00
|
|
|
ctx->flags.set(1, isClient != 0);
|
2019-12-09 12:27:58 +00:00
|
|
|
ctx->authPolicy.exchange(UDPC_AuthPolicy::UDPC_AUTH_POLICY_FALLBACK);
|
2019-09-17 11:33:47 +00:00
|
|
|
|
2019-09-20 05:26:59 +00:00
|
|
|
UDPC_CHECK_LOG(ctx, UDPC_LoggingType::UDPC_INFO, "Got listen addr ",
|
2019-09-18 08:35:14 +00:00
|
|
|
UDPC_atostr((UDPC_HContext)ctx, listenId.addr));
|
2019-09-16 02:40:43 +00:00
|
|
|
|
2019-11-18 08:37:03 +00:00
|
|
|
if(isUsingLibsodium) {
|
|
|
|
#ifdef UDPC_LIBSODIUM_ENABLED
|
|
|
|
// initialize libsodium
|
|
|
|
if(sodium_init() < 0) {
|
|
|
|
UDPC_CHECK_LOG(ctx, UDPC_LoggingType::UDPC_ERROR,
|
|
|
|
"Failed to initialize libsodium");
|
|
|
|
delete ctx;
|
|
|
|
return nullptr;
|
|
|
|
} else {
|
|
|
|
ctx->flags.set(2);
|
|
|
|
}
|
|
|
|
#else
|
2019-09-23 11:11:12 +00:00
|
|
|
UDPC_CHECK_LOG(ctx, UDPC_LoggingType::UDPC_ERROR,
|
2019-11-18 08:37:03 +00:00
|
|
|
"Cannot use libsodium, UDPC was compiled without libsodium support");
|
2019-09-23 11:11:12 +00:00
|
|
|
delete ctx;
|
|
|
|
return nullptr;
|
2019-11-18 08:37:03 +00:00
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
ctx->flags.reset(2);
|
2019-09-23 11:11:12 +00:00
|
|
|
}
|
|
|
|
|
2019-09-19 03:23:15 +00:00
|
|
|
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
|
|
|
|
// Initialize Winsock
|
|
|
|
WORD wVersionRequested = MAKEWORD(2, 2);
|
|
|
|
WSADATA wsaData;
|
|
|
|
if(WSAStartup(wVersionRequested, &wsaData) != 0) {
|
2019-09-20 05:26:59 +00:00
|
|
|
UDPC_CHECK_LOG(ctx, UDPC_LoggingType::UDPC_ERROR, "Failed to initialize Winsock");
|
2019-09-19 03:23:15 +00:00
|
|
|
delete ctx;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-09-16 02:40:43 +00:00
|
|
|
// create socket
|
|
|
|
ctx->socketHandle = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
2019-09-19 03:23:15 +00:00
|
|
|
if(UDPC_SOCKET_RETURN_ERROR(ctx->socketHandle)) {
|
2019-09-16 02:40:43 +00:00
|
|
|
// TODO maybe different way of handling init fail
|
2019-09-19 03:23:15 +00:00
|
|
|
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
|
2019-09-20 05:26:59 +00:00
|
|
|
UDPC_CHECK_LOG(ctx, UDPC_LoggingType::UDPC_ERROR, "Failed to create socket, ",
|
2019-09-19 03:23:15 +00:00
|
|
|
WSAGetLastError());
|
|
|
|
#else
|
2019-09-20 05:26:59 +00:00
|
|
|
UDPC_CHECK_LOG(ctx, UDPC_LoggingType::UDPC_ERROR, "Failed to create socket");
|
2019-09-19 03:23:15 +00:00
|
|
|
#endif
|
2019-09-16 02:40:43 +00:00
|
|
|
delete ctx;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// allow ipv4 connections on ipv6 socket
|
|
|
|
{
|
2019-09-19 03:23:15 +00:00
|
|
|
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
|
|
|
|
char no = 0;
|
|
|
|
#else
|
2019-09-16 02:40:43 +00:00
|
|
|
int no = 0;
|
2019-09-19 03:23:15 +00:00
|
|
|
#endif
|
2019-09-16 02:40:43 +00:00
|
|
|
setsockopt(ctx->socketHandle, IPPROTO_IPV6, IPV6_V6ONLY, &no, sizeof(no));
|
|
|
|
}
|
|
|
|
|
|
|
|
// bind socket
|
|
|
|
ctx->socketInfo.sin6_family = AF_INET6;
|
|
|
|
ctx->socketInfo.sin6_addr = listenId.addr;
|
|
|
|
ctx->socketInfo.sin6_port = htons(listenId.port);
|
2019-09-17 11:33:47 +00:00
|
|
|
ctx->socketInfo.sin6_flowinfo = 0;
|
2019-09-18 08:35:14 +00:00
|
|
|
ctx->socketInfo.sin6_scope_id = listenId.scope_id;
|
2019-09-16 02:40:43 +00:00
|
|
|
if(bind(ctx->socketHandle, (const struct sockaddr *)&ctx->socketInfo,
|
2019-09-19 03:23:15 +00:00
|
|
|
sizeof(UDPC_IPV6_SOCKADDR_TYPE)) < 0) {
|
2019-09-16 02:40:43 +00:00
|
|
|
// TODO maybe different way of handling init fail
|
2019-09-20 05:26:59 +00:00
|
|
|
UDPC_CHECK_LOG(ctx, UDPC_LoggingType::UDPC_ERROR, "Failed to bind socket");
|
2019-09-19 03:23:15 +00:00
|
|
|
UDPC_CLEANUPSOCKET(ctx->socketHandle);
|
2019-09-16 02:40:43 +00:00
|
|
|
delete ctx;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO verify this is necessary to get the listen port
|
|
|
|
if(ctx->socketInfo.sin6_port == 0) {
|
2019-09-19 03:23:15 +00:00
|
|
|
UDPC_IPV6_SOCKADDR_TYPE getInfo;
|
|
|
|
socklen_t size = sizeof(UDPC_IPV6_SOCKADDR_TYPE);
|
2019-09-16 02:40:43 +00:00
|
|
|
if(getsockname(ctx->socketHandle, (struct sockaddr *)&getInfo, &size) == 0) {
|
|
|
|
ctx->socketInfo.sin6_port = getInfo.sin6_port;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// set non-blocking on socket
|
|
|
|
#if UDPC_PLATFORM == UDPC_PLATFORM_MAC || UDPC_PLATFORM == UDPC_PLATFORM_LINUX
|
|
|
|
int nonblocking = 1;
|
|
|
|
if(fcntl(ctx->socketHandle, F_SETFL, O_NONBLOCK, nonblocking) == -1) {
|
|
|
|
#elif UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
|
|
|
|
DWORD nonblocking = 1;
|
|
|
|
if(ioctlsocket(ctx->socketHandle, FIONBIO, &nonblocking) != 0) {
|
|
|
|
#else
|
|
|
|
{
|
|
|
|
#endif
|
|
|
|
// TODO maybe different way of handling init fail
|
2019-09-20 05:26:59 +00:00
|
|
|
UDPC_CHECK_LOG(ctx, UDPC_LoggingType::UDPC_ERROR, "Failed to set nonblocking on socket");
|
2019-09-19 03:23:15 +00:00
|
|
|
UDPC_CLEANUPSOCKET(ctx->socketHandle);
|
2019-09-16 02:40:43 +00:00
|
|
|
delete ctx;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2019-09-20 05:26:59 +00:00
|
|
|
UDPC_CHECK_LOG(ctx, UDPC_LoggingType::UDPC_INFO, "Initialized UDPC");
|
2019-09-17 11:33:47 +00:00
|
|
|
|
2019-09-16 02:40:43 +00:00
|
|
|
return (UDPC_HContext) ctx;
|
|
|
|
}
|
|
|
|
|
|
|
|
UDPC_HContext UDPC_init_threaded_update(UDPC_ConnectionId listenId,
|
2019-11-18 08:37:03 +00:00
|
|
|
int isClient, int isUsingLibsodium) {
|
|
|
|
UDPC::Context *ctx = (UDPC::Context *)UDPC_init(listenId, isClient, isUsingLibsodium);
|
2019-09-16 02:40:43 +00:00
|
|
|
if(!ctx) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2019-11-19 11:55:20 +00:00
|
|
|
|
2019-09-16 02:40:43 +00:00
|
|
|
ctx->flags.set(0);
|
2019-12-06 11:49:30 +00:00
|
|
|
ctx->threadedSleepTime = std::chrono::milliseconds(UDPC_UPDATE_MS_DEFAULT);
|
2019-11-13 05:06:48 +00:00
|
|
|
ctx->thread = std::thread(UDPC::threadedUpdate, ctx);
|
|
|
|
|
|
|
|
UDPC_CHECK_LOG(ctx, UDPC_LoggingType::UDPC_INFO, "Initialized threaded UDPC");
|
|
|
|
|
|
|
|
return (UDPC_HContext) ctx;
|
|
|
|
}
|
|
|
|
|
|
|
|
UDPC_HContext UDPC_init_threaded_update_ms(
|
2019-11-18 08:37:03 +00:00
|
|
|
UDPC_ConnectionId listenId,
|
|
|
|
int isClient,int updateMS, int isUsingLibsodium) {
|
|
|
|
UDPC::Context *ctx = (UDPC::Context *)UDPC_init(
|
|
|
|
listenId, isClient, isUsingLibsodium);
|
2019-11-13 05:06:48 +00:00
|
|
|
if(!ctx) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2019-11-19 11:55:20 +00:00
|
|
|
|
2019-11-13 05:06:48 +00:00
|
|
|
ctx->flags.set(0);
|
2019-12-06 11:49:30 +00:00
|
|
|
if(updateMS < UDPC_UPDATE_MS_MIN) {
|
|
|
|
ctx->threadedSleepTime = std::chrono::milliseconds(UDPC_UPDATE_MS_MIN);
|
|
|
|
} else if(updateMS > UDPC_UPDATE_MS_MAX) {
|
|
|
|
ctx->threadedSleepTime = std::chrono::milliseconds(UDPC_UPDATE_MS_MAX);
|
2019-11-13 05:06:48 +00:00
|
|
|
} else {
|
|
|
|
ctx->threadedSleepTime = std::chrono::milliseconds(updateMS);
|
|
|
|
}
|
2019-09-16 02:40:43 +00:00
|
|
|
ctx->thread = std::thread(UDPC::threadedUpdate, ctx);
|
|
|
|
|
2019-09-20 05:26:59 +00:00
|
|
|
UDPC_CHECK_LOG(ctx, UDPC_LoggingType::UDPC_INFO, "Initialized threaded UDPC");
|
2019-09-17 11:33:47 +00:00
|
|
|
|
2019-09-16 02:40:43 +00:00
|
|
|
return (UDPC_HContext) ctx;
|
|
|
|
}
|
|
|
|
|
2019-11-27 10:47:51 +00:00
|
|
|
int UDPC_enable_threaded_update(UDPC_HContext ctx) {
|
2019-11-19 11:55:20 +00:00
|
|
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
|
|
|
if(!c || c->flags.test(0) || c->thread.joinable()) {
|
2019-11-27 10:47:51 +00:00
|
|
|
return 0;
|
2019-11-19 11:55:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
c->flags.set(0);
|
2019-12-06 11:49:30 +00:00
|
|
|
c->threadedSleepTime = std::chrono::milliseconds(UDPC_UPDATE_MS_DEFAULT);
|
2019-11-19 11:55:20 +00:00
|
|
|
c->threadRunning.store(true);
|
|
|
|
c->thread = std::thread(UDPC::threadedUpdate, c);
|
|
|
|
|
|
|
|
UDPC_CHECK_LOG(c, UDPC_LoggingType::UDPC_INFO, "Started threaded update");
|
2019-11-27 10:47:51 +00:00
|
|
|
return 1;
|
2019-11-19 11:55:20 +00:00
|
|
|
}
|
|
|
|
|
2019-11-27 10:47:51 +00:00
|
|
|
int UDPC_enable_threaded_update_ms(UDPC_HContext ctx, int updateMS) {
|
2019-11-19 11:55:20 +00:00
|
|
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
|
|
|
if(!c || c->flags.test(0) || c->thread.joinable()) {
|
2019-11-27 10:47:51 +00:00
|
|
|
return 0;
|
2019-11-19 11:55:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
c->flags.set(0);
|
2019-12-06 11:49:30 +00:00
|
|
|
if(updateMS < UDPC_UPDATE_MS_MIN) {
|
|
|
|
c->threadedSleepTime = std::chrono::milliseconds(UDPC_UPDATE_MS_MIN);
|
|
|
|
} else if(updateMS > UDPC_UPDATE_MS_MAX) {
|
|
|
|
c->threadedSleepTime = std::chrono::milliseconds(UDPC_UPDATE_MS_MAX);
|
2019-11-19 11:55:20 +00:00
|
|
|
} else {
|
|
|
|
c->threadedSleepTime = std::chrono::milliseconds(updateMS);
|
|
|
|
}
|
|
|
|
c->threadRunning.store(true);
|
|
|
|
c->thread = std::thread(UDPC::threadedUpdate, c);
|
|
|
|
|
|
|
|
UDPC_CHECK_LOG(c, UDPC_LoggingType::UDPC_INFO, "Started threaded update");
|
2019-11-27 10:47:51 +00:00
|
|
|
return 1;
|
2019-11-19 11:55:20 +00:00
|
|
|
}
|
|
|
|
|
2019-11-27 10:47:51 +00:00
|
|
|
int UDPC_disable_threaded_update(UDPC_HContext ctx) {
|
2019-11-19 11:55:20 +00:00
|
|
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
|
|
|
if(!c || !c->flags.test(0) || !c->thread.joinable()) {
|
2019-11-27 10:47:51 +00:00
|
|
|
return 0;
|
2019-11-19 11:55:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
c->threadRunning.store(false);
|
|
|
|
c->thread.join();
|
|
|
|
c->flags.reset(0);
|
|
|
|
|
|
|
|
UDPC_CHECK_LOG(c, UDPC_LoggingType::UDPC_INFO, "Stopped threaded update");
|
2019-11-27 10:47:51 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int UDPC_is_valid_context(UDPC_HContext ctx) {
|
|
|
|
return UDPC::verifyContext(ctx) != nullptr ? 1 : 0;
|
2019-11-19 11:55:20 +00:00
|
|
|
}
|
|
|
|
|
2019-09-16 02:40:43 +00:00
|
|
|
void UDPC_destroy(UDPC_HContext ctx) {
|
|
|
|
UDPC::Context *UDPC_ctx = UDPC::verifyContext(ctx);
|
|
|
|
if(UDPC_ctx) {
|
|
|
|
if(UDPC_ctx->flags.test(0)) {
|
|
|
|
UDPC_ctx->threadRunning.store(false);
|
|
|
|
UDPC_ctx->thread.join();
|
|
|
|
}
|
2019-09-19 03:23:15 +00:00
|
|
|
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
|
|
|
|
WSACleanup();
|
|
|
|
#endif
|
2019-11-19 11:55:20 +00:00
|
|
|
while(!UDPC_ctx->internalEvents.empty()) {
|
|
|
|
auto optE = UDPC_ctx->internalEvents.top_and_pop();
|
2019-12-17 10:12:54 +00:00
|
|
|
if(optE && optE->type == UDPC_ET_REQUEST_CONNECT_PK) {
|
|
|
|
delete[] optE->v.pk;
|
2019-11-19 11:55:20 +00:00
|
|
|
}
|
|
|
|
}
|
2019-11-27 11:12:57 +00:00
|
|
|
UDPC_ctx->_contextIdentifier = 0;
|
2019-09-16 02:40:43 +00:00
|
|
|
delete UDPC_ctx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void UDPC_update(UDPC_HContext ctx) {
|
|
|
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
|
|
|
if(!c || c->flags.test(0)) {
|
|
|
|
// invalid or is threaded, update should not be called
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-12-19 02:39:34 +00:00
|
|
|
std::lock_guard<std::mutex> lock(c->mutex);
|
2019-09-16 02:40:43 +00:00
|
|
|
c->update_impl();
|
|
|
|
}
|
|
|
|
|
2019-11-19 11:55:20 +00:00
|
|
|
void UDPC_client_initiate_connection(
|
|
|
|
UDPC_HContext ctx,
|
|
|
|
UDPC_ConnectionId connectionId,
|
|
|
|
int enableLibSodium) {
|
2019-08-29 02:07:24 +00:00
|
|
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
|
|
|
if(!c || !c->flags.test(1)) {
|
|
|
|
return;
|
|
|
|
}
|
2019-11-18 08:37:03 +00:00
|
|
|
#ifndef UDPC_LIBSODIUM_ENABLED
|
|
|
|
if(enableLibSodium) {
|
|
|
|
UDPC_CHECK_LOG(c, UDPC_LoggingType::UDPC_ERROR,
|
|
|
|
"Cannot enable libsodium, UDPC was compiled without libsodium");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
2019-08-29 02:07:24 +00:00
|
|
|
|
2019-11-18 08:37:03 +00:00
|
|
|
c->internalEvents.push(UDPC_Event{UDPC_ET_REQUEST_CONNECT, connectionId, enableLibSodium});
|
2019-08-29 02:07:24 +00:00
|
|
|
}
|
|
|
|
|
2019-11-19 11:55:20 +00:00
|
|
|
void UDPC_client_initiate_connection_pk(
|
|
|
|
UDPC_HContext ctx,
|
|
|
|
UDPC_ConnectionId connectionId,
|
|
|
|
unsigned char *serverPK) {
|
|
|
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
|
|
|
if(!c || !c->flags.test(1)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#ifndef UDPC_LIBSODIUM_ENABLED
|
|
|
|
UDPC_CHECK_LOG(c, UDPC_LoggingType::UDPC_ERROR,
|
|
|
|
"Cannot initiate connection with public key, UDPC was compiled "
|
|
|
|
"without libsodium");
|
|
|
|
return;
|
|
|
|
#else
|
|
|
|
else if(!c->flags.test(2)) {
|
|
|
|
UDPC_CHECK_LOG(c, UDPC_LoggingType::UDPC_ERROR,
|
|
|
|
"Cannot initiate connection with public key, libsodium is not "
|
|
|
|
"enabled");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
UDPC_Event event{UDPC_ET_REQUEST_CONNECT_PK, connectionId, 0};
|
|
|
|
event.v.pk = new unsigned char[crypto_sign_PUBLICKEYBYTES];
|
|
|
|
std::memcpy(event.v.pk, serverPK, crypto_sign_PUBLICKEYBYTES);
|
|
|
|
c->internalEvents.push(event);
|
|
|
|
}
|
|
|
|
|
2019-09-07 07:36:11 +00:00
|
|
|
void UDPC_queue_send(UDPC_HContext ctx, UDPC_ConnectionId destinationId,
|
2019-09-20 05:01:26 +00:00
|
|
|
int isChecked, void *data, uint32_t size) {
|
2019-08-27 05:06:27 +00:00
|
|
|
if(size == 0 || !data) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-07-21 04:45:42 +00:00
|
|
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
|
|
|
if(!c) {
|
2019-06-06 07:02:48 +00:00
|
|
|
return;
|
2019-08-27 05:06:27 +00:00
|
|
|
}
|
|
|
|
|
2019-09-07 07:36:11 +00:00
|
|
|
UDPC_PacketInfo sendInfo = UDPC::get_empty_pinfo();
|
2019-08-27 05:06:27 +00:00
|
|
|
std::memcpy(sendInfo.data, data, size);
|
|
|
|
sendInfo.dataSize = size;
|
2019-09-07 07:36:11 +00:00
|
|
|
sendInfo.sender.addr = in6addr_loopback;
|
2019-09-23 11:11:12 +00:00
|
|
|
sendInfo.sender.port = ntohs(c->socketInfo.sin6_port);
|
2019-09-07 07:36:11 +00:00
|
|
|
sendInfo.receiver.addr = destinationId.addr;
|
2019-09-27 11:19:48 +00:00
|
|
|
sendInfo.receiver.port = destinationId.port;
|
2019-09-20 05:01:26 +00:00
|
|
|
sendInfo.flags = (isChecked != 0 ? 0x0 : 0x4);
|
2019-08-27 05:06:27 +00:00
|
|
|
|
2019-09-27 11:19:48 +00:00
|
|
|
c->cSendPkts.push(sendInfo);
|
2019-06-06 07:02:48 +00:00
|
|
|
}
|
|
|
|
|
2019-11-06 05:35:16 +00:00
|
|
|
unsigned long UDPC_get_queue_send_current_size(UDPC_HContext ctx) {
|
|
|
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
|
|
|
if(!c) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return c->cSendPkts.size();
|
|
|
|
}
|
|
|
|
|
2019-12-18 04:47:46 +00:00
|
|
|
unsigned long UDPC_get_queued_size(UDPC_HContext ctx, UDPC_ConnectionId id, int *exists) {
|
|
|
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
|
|
|
if(!c) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(c->mutex);
|
|
|
|
auto iter = c->conMap.find(id);
|
|
|
|
if(iter != c->conMap.end()) {
|
|
|
|
if(exists) {
|
|
|
|
*exists = 1;
|
|
|
|
}
|
|
|
|
return iter->second.sendPkts.size();
|
|
|
|
}
|
|
|
|
if(exists) {
|
|
|
|
*exists = 0;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned long UDPC_get_max_queued_size() {
|
|
|
|
return UDPC_QUEUED_PKTS_MAX_SIZE;
|
|
|
|
}
|
|
|
|
|
2019-08-30 03:03:26 +00:00
|
|
|
int UDPC_set_accept_new_connections(UDPC_HContext ctx, int isAccepting) {
|
2019-07-21 04:45:42 +00:00
|
|
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
|
|
|
if(!c) {
|
2019-06-06 07:02:48 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2019-11-27 11:12:57 +00:00
|
|
|
return c->isAcceptNewConnections.exchange(isAccepting == 0 ? false : true)
|
|
|
|
? 1 : 0;
|
2019-06-06 07:02:48 +00:00
|
|
|
}
|
|
|
|
|
2019-11-11 07:08:51 +00:00
|
|
|
void UDPC_drop_connection(UDPC_HContext ctx, UDPC_ConnectionId connectionId, int dropAllWithAddr) {
|
2019-07-21 04:45:42 +00:00
|
|
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
|
|
|
if(!c) {
|
2019-11-11 07:08:51 +00:00
|
|
|
return;
|
2019-08-28 07:38:14 +00:00
|
|
|
}
|
|
|
|
|
2019-11-11 07:08:51 +00:00
|
|
|
c->internalEvents.push(UDPC_Event{UDPC_ET_REQUEST_DISCONNECT, connectionId, dropAllWithAddr});
|
|
|
|
return;
|
2019-08-28 07:38:14 +00:00
|
|
|
}
|
|
|
|
|
2019-09-17 11:33:47 +00:00
|
|
|
int UDPC_has_connection(UDPC_HContext ctx, UDPC_ConnectionId connectionId) {
|
|
|
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
|
|
|
if(!c) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(c->mutex);
|
|
|
|
|
|
|
|
return c->conMap.find(connectionId) == c->conMap.end() ? 0 : 1;
|
|
|
|
}
|
|
|
|
|
2019-09-20 05:01:26 +00:00
|
|
|
UDPC_ConnectionId* UDPC_get_list_connected(UDPC_HContext ctx, unsigned int *size) {
|
|
|
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
|
|
|
if(!c) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(c->mutex);
|
|
|
|
|
|
|
|
if(c->conMap.empty()) {
|
2019-12-17 11:58:44 +00:00
|
|
|
if(size) {
|
|
|
|
*size = 0;
|
|
|
|
}
|
2019-09-20 05:01:26 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if(size) {
|
|
|
|
*size = c->conMap.size();
|
|
|
|
}
|
|
|
|
|
2019-12-18 05:34:53 +00:00
|
|
|
UDPC_ConnectionId *list = (UDPC_ConnectionId*)std::calloc(
|
|
|
|
c->conMap.size() + 1, sizeof(UDPC_ConnectionId));
|
2019-09-20 05:01:26 +00:00
|
|
|
UDPC_ConnectionId *current = list;
|
|
|
|
for(auto iter = c->conMap.begin(); iter != c->conMap.end(); ++iter) {
|
|
|
|
*current = iter->first;
|
|
|
|
++current;
|
|
|
|
}
|
2019-12-18 05:34:53 +00:00
|
|
|
// following line is redudnant, since calloc initialized all bits to zero
|
|
|
|
// *current = UDPC_ConnectionId{{0}, 0, 0};
|
2019-09-20 05:01:26 +00:00
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
void UDPC_free_list_connected(UDPC_ConnectionId *list) {
|
|
|
|
std::free(list);
|
|
|
|
}
|
|
|
|
|
2019-11-11 07:08:51 +00:00
|
|
|
uint32_t UDPC_get_protocol_id(UDPC_HContext ctx) {
|
|
|
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
|
|
|
if(!c) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return c->protocolID.load();
|
|
|
|
}
|
|
|
|
|
2019-08-30 03:03:26 +00:00
|
|
|
uint32_t UDPC_set_protocol_id(UDPC_HContext ctx, uint32_t id) {
|
2019-07-21 04:45:42 +00:00
|
|
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
|
|
|
if(!c) {
|
2019-06-06 07:02:48 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2019-11-11 07:08:51 +00:00
|
|
|
|
2019-06-06 07:02:48 +00:00
|
|
|
return c->protocolID.exchange(id);
|
|
|
|
}
|
|
|
|
|
2019-11-11 07:08:51 +00:00
|
|
|
UDPC_LoggingType UDPC_get_logging_type(UDPC_HContext ctx) {
|
|
|
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
|
|
|
if(!c) {
|
|
|
|
return UDPC_LoggingType::UDPC_SILENT;
|
|
|
|
}
|
|
|
|
return static_cast<UDPC_LoggingType>(c->loggingType.load());
|
|
|
|
}
|
|
|
|
|
2019-09-17 11:33:47 +00:00
|
|
|
UDPC_LoggingType UDPC_set_logging_type(UDPC_HContext ctx, UDPC_LoggingType loggingType) {
|
2019-07-21 04:45:42 +00:00
|
|
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
|
|
|
if(!c) {
|
2019-09-19 01:58:19 +00:00
|
|
|
return UDPC_LoggingType::UDPC_SILENT;
|
2019-06-06 07:02:48 +00:00
|
|
|
}
|
|
|
|
return static_cast<UDPC_LoggingType>(c->loggingType.exchange(loggingType));
|
|
|
|
}
|
|
|
|
|
2019-11-11 07:08:51 +00:00
|
|
|
int UDPC_get_receiving_events(UDPC_HContext ctx) {
|
|
|
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
|
|
|
if(!c) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return c->isReceivingEvents.load() ? 1 : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int UDPC_set_receiving_events(UDPC_HContext ctx, int isReceivingEvents) {
|
|
|
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
|
|
|
if(!c) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return c->isReceivingEvents.exchange(isReceivingEvents != 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
UDPC_Event UDPC_get_event(UDPC_HContext ctx, unsigned long *remaining) {
|
|
|
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
|
|
|
if(!c) {
|
|
|
|
return UDPC_Event{UDPC_ET_NONE, UDPC_create_id_anyaddr(0), 0};
|
|
|
|
}
|
|
|
|
|
|
|
|
auto optE = c->externalEvents.top_and_pop_and_rsize(remaining);
|
|
|
|
if(optE) {
|
2019-12-17 10:12:54 +00:00
|
|
|
return *optE;
|
2019-11-11 07:08:51 +00:00
|
|
|
} else {
|
|
|
|
return UDPC_Event{UDPC_ET_NONE, UDPC_create_id_anyaddr(0), 0};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-06 05:35:16 +00:00
|
|
|
UDPC_PacketInfo UDPC_get_received(UDPC_HContext ctx, unsigned long *remaining) {
|
2019-07-21 04:45:42 +00:00
|
|
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
|
|
|
if(!c) {
|
2019-09-07 07:36:11 +00:00
|
|
|
return UDPC::get_empty_pinfo();
|
2019-06-06 07:02:48 +00:00
|
|
|
}
|
2019-09-16 03:00:25 +00:00
|
|
|
|
2019-09-20 07:59:16 +00:00
|
|
|
auto opt_pinfo = c->receivedPkts.top_and_pop_and_rsize(remaining);
|
2019-09-20 05:01:26 +00:00
|
|
|
if(opt_pinfo) {
|
|
|
|
return *opt_pinfo;
|
|
|
|
}
|
2019-09-07 07:36:11 +00:00
|
|
|
return UDPC::get_empty_pinfo();
|
2019-06-06 07:02:48 +00:00
|
|
|
}
|
|
|
|
|
2019-11-27 10:41:38 +00:00
|
|
|
int UDPC_set_libsodium_keys(UDPC_HContext ctx, unsigned char *sk, unsigned char *pk) {
|
2019-11-19 11:55:20 +00:00
|
|
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
|
|
|
if(!c || !c->flags.test(2)) {
|
2019-11-27 10:41:38 +00:00
|
|
|
return 0;
|
2019-11-19 11:55:20 +00:00
|
|
|
}
|
|
|
|
|
2019-11-21 03:23:40 +00:00
|
|
|
std::lock_guard<std::mutex> lock(c->mutex);
|
2019-11-19 11:55:20 +00:00
|
|
|
std::memcpy(c->sk, sk, crypto_sign_SECRETKEYBYTES);
|
|
|
|
std::memcpy(c->pk, pk, crypto_sign_PUBLICKEYBYTES);
|
|
|
|
c->keysSet.store(true);
|
2019-11-27 10:41:38 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int UDPC_set_libsodium_key_easy(UDPC_HContext ctx, unsigned char *sk) {
|
|
|
|
unsigned char pk[crypto_sign_PUBLICKEYBYTES];
|
|
|
|
if(crypto_sign_ed25519_sk_to_pk(pk, sk) != 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return UDPC_set_libsodium_keys(ctx, sk, pk);
|
2019-11-19 11:55:20 +00:00
|
|
|
}
|
|
|
|
|
2019-11-27 11:12:57 +00:00
|
|
|
int UDPC_unset_libsodium_keys(UDPC_HContext ctx) {
|
2019-11-21 03:23:40 +00:00
|
|
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
|
|
|
if(!c || !c->flags.test(2)) {
|
2019-11-27 11:12:57 +00:00
|
|
|
return 0;
|
2019-11-21 03:23:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(c->mutex);
|
|
|
|
c->keysSet.store(false);
|
2019-11-27 11:12:57 +00:00
|
|
|
std::memset(c->pk, 0, crypto_sign_PUBLICKEYBYTES);
|
|
|
|
std::memset(c->sk, 0, crypto_sign_SECRETKEYBYTES);
|
|
|
|
return 1;
|
2019-11-21 03:23:40 +00:00
|
|
|
}
|
|
|
|
|
2019-12-09 12:27:58 +00:00
|
|
|
int UDPC_get_auth_policy(UDPC_HContext ctx) {
|
|
|
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
|
|
|
if(!c) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return c->authPolicy.load();
|
|
|
|
}
|
|
|
|
|
|
|
|
int UDPC_set_auth_policy(UDPC_HContext ctx, int policy) {
|
|
|
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
|
|
|
if(!c) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isInRange = false;
|
|
|
|
for(int i = 0; i < UDPC_AuthPolicy::UDPC_AUTH_POLICY_SIZE; ++i) {
|
|
|
|
if(policy == i) {
|
|
|
|
isInRange = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!isInRange) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return c->authPolicy.exchange(policy);
|
|
|
|
}
|
|
|
|
|
2019-09-18 08:35:14 +00:00
|
|
|
const char *UDPC_atostr_cid(UDPC_HContext ctx, UDPC_ConnectionId connectionId) {
|
|
|
|
return UDPC_atostr(ctx, connectionId.addr);
|
|
|
|
}
|
|
|
|
|
2019-09-19 03:23:15 +00:00
|
|
|
const char *UDPC_atostr(UDPC_HContext ctx, UDPC_IPV6_ADDR_TYPE addr) {
|
2019-07-21 04:45:42 +00:00
|
|
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
|
|
|
if(!c) {
|
2019-06-06 07:02:48 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
2019-09-03 07:19:47 +00:00
|
|
|
const uint32_t headIndex =
|
|
|
|
c->atostrBufIndex.fetch_add(UDPC_ATOSTR_BUFSIZE) % UDPC_ATOSTR_SIZE;
|
|
|
|
uint32_t index = headIndex;
|
2019-09-07 07:36:11 +00:00
|
|
|
bool usedDouble = false;
|
|
|
|
|
|
|
|
for(unsigned int i = 0; i < 16; ++i) {
|
|
|
|
if(i != 0 && i % 2 == 0) {
|
|
|
|
if(headIndex - index > 1 && c->atostrBuf[index - 1] == ':') {
|
|
|
|
if(usedDouble) {
|
|
|
|
if(c->atostrBuf[index - 2] != ':') {
|
|
|
|
c->atostrBuf[index++] = '0';
|
|
|
|
c->atostrBuf[index++] = ':';
|
|
|
|
} else {
|
|
|
|
// continue use of double :, do nothing here
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
usedDouble = true;
|
|
|
|
c->atostrBuf[index++] = ':';
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
c->atostrBuf[index++] = ':';
|
|
|
|
}
|
2019-06-06 07:02:48 +00:00
|
|
|
}
|
|
|
|
|
2019-09-20 05:01:26 +00:00
|
|
|
if(UDPC_IPV6_ADDR_SUB(addr)[i] == 0
|
|
|
|
&& (headIndex - index <= 1 || c->atostrBuf[index] == ':')) {
|
2019-09-07 07:36:11 +00:00
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
std::stringstream sstream;
|
2019-09-18 09:39:35 +00:00
|
|
|
sstream << std::setw(2) << std::setfill('0')
|
2019-09-19 03:23:15 +00:00
|
|
|
<< std::hex << (unsigned int) UDPC_IPV6_ADDR_SUB(addr)[i];
|
2019-09-07 07:36:11 +00:00
|
|
|
std::string out(sstream.str());
|
2019-09-18 09:39:35 +00:00
|
|
|
unsigned int outOffset = 0;
|
|
|
|
if(headIndex - index <= 1 || c->atostrBuf[index - 1] == ':') {
|
|
|
|
if(out[0] == '0') {
|
|
|
|
if(out[1] == '0') {
|
|
|
|
outOffset = 2;
|
|
|
|
} else {
|
|
|
|
outOffset = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(outOffset == 2) {
|
|
|
|
continue;
|
|
|
|
} else if(outOffset == 1) {
|
|
|
|
if(out[outOffset] != '0') {
|
|
|
|
std::memcpy(c->atostrBuf + index, out.c_str() + outOffset, 1);
|
2019-09-07 07:36:11 +00:00
|
|
|
++index;
|
|
|
|
}
|
|
|
|
} else {
|
2019-09-18 09:39:35 +00:00
|
|
|
std::memcpy(c->atostrBuf + index, out.c_str() + outOffset, 2);
|
2019-09-07 07:36:11 +00:00
|
|
|
index += 2;
|
|
|
|
}
|
2019-06-06 07:02:48 +00:00
|
|
|
}
|
|
|
|
}
|
2019-09-07 07:36:11 +00:00
|
|
|
if(c->atostrBuf[index - 1] == ':'
|
|
|
|
&& (headIndex - index <= 2 || c->atostrBuf[index - 2] != ':')) {
|
|
|
|
c->atostrBuf[index++] = '0';
|
|
|
|
}
|
|
|
|
|
2019-06-06 07:02:48 +00:00
|
|
|
c->atostrBuf[index] = 0;
|
|
|
|
|
2019-09-03 07:19:47 +00:00
|
|
|
return c->atostrBuf + headIndex;
|
2019-06-06 07:02:48 +00:00
|
|
|
}
|
|
|
|
|
2019-09-19 03:23:15 +00:00
|
|
|
UDPC_IPV6_ADDR_TYPE UDPC_strtoa(const char *addrStr) {
|
|
|
|
UDPC_IPV6_ADDR_TYPE result = in6addr_loopback;
|
2019-09-17 08:17:16 +00:00
|
|
|
std::cmatch matchResults;
|
|
|
|
if(std::regex_match(addrStr, matchResults, ipv6_regex_nolink)) {
|
2019-12-18 05:20:29 +00:00
|
|
|
if(std::strcmp("::", addrStr) == 0) {
|
|
|
|
return in6addr_any;
|
|
|
|
}
|
|
|
|
|
2019-09-17 08:17:16 +00:00
|
|
|
unsigned int index = 0;
|
|
|
|
unsigned int strIndex = 0;
|
|
|
|
int doubleColonIndex = -1;
|
|
|
|
unsigned char bytes[2] = {0, 0};
|
|
|
|
unsigned char bytesState = 0;
|
|
|
|
bool prevColon = false;
|
|
|
|
|
|
|
|
const auto checkInc = [&result, &index, &bytes] () -> bool {
|
|
|
|
if(index < 15) {
|
2019-09-19 03:23:15 +00:00
|
|
|
UDPC_IPV6_ADDR_SUB(result)[index++] = bytes[0];
|
|
|
|
UDPC_IPV6_ADDR_SUB(result)[index++] = bytes[1];
|
2019-09-17 08:17:16 +00:00
|
|
|
bytes[0] = 0;
|
|
|
|
bytes[1] = 0;
|
|
|
|
return false;
|
2019-09-07 07:36:11 +00:00
|
|
|
}
|
2019-09-17 08:17:16 +00:00
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
|
|
|
while(addrStr[strIndex] != '\0') {
|
|
|
|
if(addrStr[strIndex] >= '0' && addrStr[strIndex] <= '9') {
|
|
|
|
switch(bytesState) {
|
|
|
|
case 0:
|
|
|
|
bytes[0] = (addrStr[strIndex] - '0');
|
|
|
|
bytesState = 1;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
bytes[0] = (bytes[0] << 4) | (addrStr[strIndex] - '0');
|
|
|
|
bytesState = 2;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
bytes[1] = (addrStr[strIndex] - '0');
|
|
|
|
bytesState = 3;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
bytes[1] = (bytes[1] << 4) | (addrStr[strIndex] - '0');
|
|
|
|
bytesState = 0;
|
|
|
|
if(checkInc()) {
|
|
|
|
return in6addr_loopback;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2019-09-07 07:36:11 +00:00
|
|
|
return in6addr_loopback;
|
|
|
|
}
|
2019-09-17 08:17:16 +00:00
|
|
|
prevColon = false;
|
|
|
|
} else if(addrStr[strIndex] >= 'a' && addrStr[strIndex] <= 'f') {
|
|
|
|
switch(bytesState) {
|
|
|
|
case 0:
|
|
|
|
bytes[0] = (addrStr[strIndex] - 'a' + 10);
|
|
|
|
bytesState = 1;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
bytes[0] = (bytes[0] << 4) | (addrStr[strIndex] - 'a' + 10);
|
|
|
|
bytesState = 2;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
bytes[1] = (addrStr[strIndex] - 'a' + 10);
|
|
|
|
bytesState = 3;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
bytes[1] = (bytes[1] << 4) | (addrStr[strIndex] - 'a' + 10);
|
|
|
|
bytesState = 0;
|
|
|
|
if(checkInc()) {
|
|
|
|
return in6addr_loopback;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2019-09-07 07:36:11 +00:00
|
|
|
return in6addr_loopback;
|
|
|
|
}
|
2019-09-17 08:17:16 +00:00
|
|
|
prevColon = false;
|
|
|
|
} else if(addrStr[strIndex] >= 'A' && addrStr[strIndex] <= 'F') {
|
|
|
|
switch(bytesState) {
|
|
|
|
case 0:
|
|
|
|
bytes[0] = (addrStr[strIndex] - 'A' + 10);
|
|
|
|
bytesState = 1;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
bytes[0] = (bytes[0] << 4) | (addrStr[strIndex] - 'A' + 10);
|
|
|
|
bytesState = 2;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
bytes[1] = (addrStr[strIndex] - 'A' + 10);
|
|
|
|
bytesState = 3;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
bytes[1] = (bytes[1] << 4) | (addrStr[strIndex] - 'A' + 10);
|
|
|
|
bytesState = 0;
|
|
|
|
if(checkInc()) {
|
|
|
|
return in6addr_loopback;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2019-09-07 07:36:11 +00:00
|
|
|
return in6addr_loopback;
|
|
|
|
}
|
2019-09-17 08:17:16 +00:00
|
|
|
prevColon = false;
|
|
|
|
} else if(addrStr[strIndex] == ':') {
|
|
|
|
switch(bytesState) {
|
|
|
|
case 1:
|
|
|
|
case 2:
|
|
|
|
bytes[1] = bytes[0];
|
|
|
|
bytes[0] = 0;
|
|
|
|
if(checkInc()) {
|
|
|
|
return in6addr_loopback;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
bytes[1] |= (bytes[0] & 0xF) << 4;
|
|
|
|
bytes[0] = bytes[0] >> 4;
|
|
|
|
if(checkInc()) {
|
|
|
|
return in6addr_loopback;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0:
|
|
|
|
break;
|
|
|
|
default:
|
2019-09-07 07:36:11 +00:00
|
|
|
return in6addr_loopback;
|
|
|
|
}
|
2019-09-17 08:17:16 +00:00
|
|
|
bytesState = 0;
|
|
|
|
if(prevColon) {
|
|
|
|
if(doubleColonIndex >= 0) {
|
|
|
|
return in6addr_loopback;
|
|
|
|
} else {
|
|
|
|
doubleColonIndex = index;
|
|
|
|
}
|
2019-09-07 07:36:11 +00:00
|
|
|
} else {
|
2019-09-17 08:17:16 +00:00
|
|
|
prevColon = true;
|
2019-09-07 07:36:11 +00:00
|
|
|
}
|
2019-07-07 05:44:37 +00:00
|
|
|
} else {
|
2019-09-17 08:17:16 +00:00
|
|
|
return in6addr_loopback;
|
2019-07-07 05:44:37 +00:00
|
|
|
}
|
2019-09-07 07:36:11 +00:00
|
|
|
|
2019-09-17 08:17:16 +00:00
|
|
|
++strIndex;
|
2019-09-07 07:36:11 +00:00
|
|
|
}
|
2019-09-17 08:17:16 +00:00
|
|
|
switch(bytesState) {
|
|
|
|
case 1:
|
|
|
|
case 2:
|
|
|
|
bytes[1] = bytes[0];
|
|
|
|
bytes[0] = 0;
|
|
|
|
if(checkInc()) {
|
|
|
|
return in6addr_loopback;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
bytes[1] |= (bytes[0] & 0xF) << 4;
|
|
|
|
bytes[0] = bytes[0] >> 4;
|
|
|
|
if(checkInc()) {
|
|
|
|
return in6addr_loopback;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0:
|
|
|
|
break;
|
|
|
|
default:
|
2019-09-07 07:36:11 +00:00
|
|
|
return in6addr_loopback;
|
2019-06-06 07:02:48 +00:00
|
|
|
}
|
|
|
|
|
2019-09-17 08:17:16 +00:00
|
|
|
if(doubleColonIndex >= 0) {
|
|
|
|
strIndex = 16 - index;
|
|
|
|
if(strIndex < 2) {
|
|
|
|
return in6addr_loopback;
|
|
|
|
}
|
|
|
|
for(unsigned int i = 16; i-- > (unsigned int)doubleColonIndex + strIndex; ) {
|
2019-09-19 03:23:15 +00:00
|
|
|
UDPC_IPV6_ADDR_SUB(result)[i] = UDPC_IPV6_ADDR_SUB(result)[i - strIndex];
|
|
|
|
UDPC_IPV6_ADDR_SUB(result)[i - strIndex] = 0;
|
2019-09-17 08:17:16 +00:00
|
|
|
}
|
2019-09-07 07:36:11 +00:00
|
|
|
}
|
2019-09-17 08:17:16 +00:00
|
|
|
} else if(std::regex_match(addrStr, matchResults, ipv4_regex)) {
|
|
|
|
for(unsigned int i = 0; i < 10; ++i) {
|
2019-09-19 03:23:15 +00:00
|
|
|
UDPC_IPV6_ADDR_SUB(result)[i] = 0;
|
2019-09-17 08:17:16 +00:00
|
|
|
}
|
2019-09-19 03:23:15 +00:00
|
|
|
UDPC_IPV6_ADDR_SUB(result)[10] = 0xFF;
|
|
|
|
UDPC_IPV6_ADDR_SUB(result)[11] = 0xFF;
|
2019-09-17 08:17:16 +00:00
|
|
|
for(unsigned int i = 0; i < 4; ++i) {
|
2019-09-19 03:23:15 +00:00
|
|
|
UDPC_IPV6_ADDR_SUB(result)[12 + i] = std::stoi(matchResults[i + 1].str());
|
2019-07-07 05:44:37 +00:00
|
|
|
}
|
2019-06-06 07:02:48 +00:00
|
|
|
}
|
2019-09-07 07:36:11 +00:00
|
|
|
return result;
|
2019-06-06 07:02:48 +00:00
|
|
|
}
|
2019-09-18 08:35:14 +00:00
|
|
|
|
2019-09-19 03:23:15 +00:00
|
|
|
UDPC_IPV6_ADDR_TYPE UDPC_strtoa_link(const char *addrStr, uint32_t *linkId_out) {
|
2019-09-18 08:35:14 +00:00
|
|
|
const auto checkSetOut = [&linkId_out] (uint32_t val) {
|
|
|
|
if(linkId_out) {
|
|
|
|
*linkId_out = val;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-09-19 03:23:15 +00:00
|
|
|
UDPC_IPV6_ADDR_TYPE result({0});
|
2019-09-18 08:35:14 +00:00
|
|
|
std::cmatch matchResults;
|
|
|
|
const char *linkName = nullptr;
|
|
|
|
|
|
|
|
if(std::regex_match(addrStr, matchResults, ipv6_regex_linkonly)) {
|
|
|
|
unsigned int index = 0;
|
|
|
|
unsigned int strIndex = 0;
|
|
|
|
int doubleColonIndex = -1;
|
|
|
|
unsigned char bytes[2] = {0, 0};
|
|
|
|
unsigned char bytesState = 0;
|
|
|
|
bool prevColon = false;
|
|
|
|
|
|
|
|
const auto checkInc = [&result, &index, &bytes] () -> bool {
|
|
|
|
if(index < 15) {
|
2019-09-19 03:23:15 +00:00
|
|
|
UDPC_IPV6_ADDR_SUB(result)[index++] = bytes[0];
|
|
|
|
UDPC_IPV6_ADDR_SUB(result)[index++] = bytes[1];
|
2019-09-18 08:35:14 +00:00
|
|
|
bytes[0] = 0;
|
|
|
|
bytes[1] = 0;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
|
|
|
while(addrStr[strIndex] != '%') {
|
|
|
|
if(addrStr[strIndex] >= '0' && addrStr[strIndex] <= '9') {
|
|
|
|
switch(bytesState) {
|
|
|
|
case 0:
|
|
|
|
bytes[0] = (addrStr[strIndex] - '0');
|
|
|
|
bytesState = 1;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
bytes[0] = (bytes[0] << 4) | (addrStr[strIndex] - '0');
|
|
|
|
bytesState = 2;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
bytes[1] = (addrStr[strIndex] - '0');
|
|
|
|
bytesState = 3;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
bytes[1] = (bytes[1] << 4) | (addrStr[strIndex] - '0');
|
|
|
|
bytesState = 0;
|
|
|
|
if(checkInc()) {
|
|
|
|
checkSetOut(0);
|
|
|
|
return in6addr_loopback;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
checkSetOut(0);
|
|
|
|
return in6addr_loopback;
|
|
|
|
}
|
|
|
|
prevColon = false;
|
|
|
|
} else if(addrStr[strIndex] >= 'a' && addrStr[strIndex] <= 'f') {
|
|
|
|
switch(bytesState) {
|
|
|
|
case 0:
|
|
|
|
bytes[0] = (addrStr[strIndex] - 'a' + 10);
|
|
|
|
bytesState = 1;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
bytes[0] = (bytes[0] << 4) | (addrStr[strIndex] - 'a' + 10);
|
|
|
|
bytesState = 2;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
bytes[1] = (addrStr[strIndex] - 'a' + 10);
|
|
|
|
bytesState = 3;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
bytes[1] = (bytes[1] << 4) | (addrStr[strIndex] - 'a' + 10);
|
|
|
|
bytesState = 0;
|
|
|
|
if(checkInc()) {
|
|
|
|
checkSetOut(0);
|
|
|
|
return in6addr_loopback;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
checkSetOut(0);
|
|
|
|
return in6addr_loopback;
|
|
|
|
}
|
|
|
|
prevColon = false;
|
|
|
|
} else if(addrStr[strIndex] >= 'A' && addrStr[strIndex] <= 'F') {
|
|
|
|
switch(bytesState) {
|
|
|
|
case 0:
|
|
|
|
bytes[0] = (addrStr[strIndex] - 'A' + 10);
|
|
|
|
bytesState = 1;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
bytes[0] = (bytes[0] << 4) | (addrStr[strIndex] - 'A' + 10);
|
|
|
|
bytesState = 2;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
bytes[1] = (addrStr[strIndex] - 'A' + 10);
|
|
|
|
bytesState = 3;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
bytes[1] = (bytes[1] << 4) | (addrStr[strIndex] - 'A' + 10);
|
|
|
|
bytesState = 0;
|
|
|
|
if(checkInc()) {
|
|
|
|
checkSetOut(0);
|
|
|
|
return in6addr_loopback;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
checkSetOut(0);
|
|
|
|
return in6addr_loopback;
|
|
|
|
}
|
|
|
|
prevColon = false;
|
|
|
|
} else if(addrStr[strIndex] == ':') {
|
|
|
|
switch(bytesState) {
|
|
|
|
case 1:
|
|
|
|
case 2:
|
|
|
|
bytes[1] = bytes[0];
|
|
|
|
bytes[0] = 0;
|
|
|
|
if(checkInc()) {
|
|
|
|
checkSetOut(0);
|
|
|
|
return in6addr_loopback;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
bytes[1] |= (bytes[0] & 0xF) << 4;
|
|
|
|
bytes[0] = bytes[0] >> 4;
|
|
|
|
if(checkInc()) {
|
|
|
|
checkSetOut(0);
|
|
|
|
return in6addr_loopback;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
checkSetOut(0);
|
|
|
|
return in6addr_loopback;
|
|
|
|
}
|
|
|
|
bytesState = 0;
|
|
|
|
if(prevColon) {
|
|
|
|
if(doubleColonIndex >= 0) {
|
|
|
|
checkSetOut(0);
|
|
|
|
return in6addr_loopback;
|
|
|
|
} else {
|
|
|
|
doubleColonIndex = index;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
prevColon = true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
checkSetOut(0);
|
|
|
|
return in6addr_loopback;
|
|
|
|
}
|
|
|
|
|
|
|
|
++strIndex;
|
|
|
|
}
|
|
|
|
switch(bytesState) {
|
|
|
|
case 1:
|
|
|
|
case 2:
|
|
|
|
bytes[1] = bytes[0];
|
|
|
|
bytes[0] = 0;
|
|
|
|
if(checkInc()) {
|
|
|
|
checkSetOut(0);
|
|
|
|
return in6addr_loopback;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
bytes[1] |= (bytes[0] & 0xF) << 4;
|
|
|
|
bytes[0] = bytes[0] >> 4;
|
|
|
|
if(checkInc()) {
|
|
|
|
checkSetOut(0);
|
|
|
|
return in6addr_loopback;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
checkSetOut(0);
|
|
|
|
return in6addr_loopback;
|
|
|
|
}
|
|
|
|
linkName = addrStr + strIndex + 1;
|
|
|
|
|
|
|
|
if(doubleColonIndex >= 0) {
|
|
|
|
strIndex = 16 - index;
|
|
|
|
if(strIndex < 2) {
|
|
|
|
checkSetOut(0);
|
|
|
|
return in6addr_loopback;
|
|
|
|
}
|
|
|
|
for(unsigned int i = 16; i-- > (unsigned int)doubleColonIndex + strIndex; ) {
|
2019-09-19 03:23:15 +00:00
|
|
|
UDPC_IPV6_ADDR_SUB(result)[i] = UDPC_IPV6_ADDR_SUB(result)[i - strIndex];
|
|
|
|
UDPC_IPV6_ADDR_SUB(result)[i - strIndex] = 0;
|
2019-09-18 08:35:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-09-19 01:35:22 +00:00
|
|
|
|
|
|
|
uint32_t scope_id;
|
2019-09-19 03:23:15 +00:00
|
|
|
if(std::regex_match(linkName, regex_numeric)) {
|
|
|
|
scope_id = std::atoi(linkName);
|
2019-09-19 05:30:10 +00:00
|
|
|
}
|
|
|
|
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
|
|
|
|
else {
|
2019-09-19 03:23:15 +00:00
|
|
|
scope_id = if_nametoindex(linkName);
|
|
|
|
if(scope_id == 0) {
|
|
|
|
checkSetOut(0);
|
|
|
|
return in6addr_loopback;
|
|
|
|
}
|
2019-09-19 01:35:22 +00:00
|
|
|
}
|
|
|
|
#elif UDPC_PLATFORM == UDPC_PLATFORM_MAC || UDPC_PLATFORM == UDPC_PLATFORM_LINUX
|
2019-09-19 05:30:10 +00:00
|
|
|
else {
|
|
|
|
struct ifreq req{{0}, 0, 0};
|
|
|
|
std::strncpy(req.ifr_name, linkName, IFNAMSIZ);
|
|
|
|
int socketHandle = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
|
|
|
if(ioctl(socketHandle, SIOCGIFINDEX, &req) < 0) {
|
|
|
|
UDPC_CLEANUPSOCKET(socketHandle);
|
|
|
|
checkSetOut(0);
|
|
|
|
return in6addr_loopback;
|
|
|
|
}
|
|
|
|
scope_id = req.ifr_ifindex;
|
2019-09-19 03:23:15 +00:00
|
|
|
UDPC_CLEANUPSOCKET(socketHandle);
|
2019-09-18 08:35:14 +00:00
|
|
|
}
|
2019-09-19 01:35:22 +00:00
|
|
|
#endif
|
2019-09-18 08:35:14 +00:00
|
|
|
|
2019-09-19 01:35:22 +00:00
|
|
|
checkSetOut(scope_id);
|
2019-09-18 08:35:14 +00:00
|
|
|
return result;
|
|
|
|
}
|