libsodium support is now optional
Packet struture has been changed to support UDPC without libsodium sending packets to UDPC with libsodium.
This commit is contained in:
parent
f2b4672318
commit
4cfe35ecd1
5 changed files with 456 additions and 121 deletions
|
@ -34,11 +34,21 @@ if(WIN32)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(PkgConfig REQUIRED)
|
if(UDPC_DISABLE_LIBSODIUM)
|
||||||
pkg_check_modules(LIBSODIUM REQUIRED libsodium)
|
message(STATUS "libsodium disabled")
|
||||||
target_link_libraries(UDPConnection PUBLIC ${LIBSODIUM_LIBRARIES})
|
else()
|
||||||
target_include_directories(UDPConnection PUBLIC ${LIBSODIUM_INCLUDE_DIRS})
|
find_package(PkgConfig REQUIRED)
|
||||||
target_compile_options(UDPConnection PUBLIC ${LIBSODIUM_CFLAGS_OTHER})
|
pkg_check_modules(LIBSODIUM QUIET libsodium)
|
||||||
|
if(LIBSODIUM_FOUND)
|
||||||
|
target_compile_definitions(UDPConnection PUBLIC UDPC_LIBSODIUM_ENABLED)
|
||||||
|
target_link_libraries(UDPConnection PUBLIC ${LIBSODIUM_LIBRARIES})
|
||||||
|
target_include_directories(UDPConnection PUBLIC ${LIBSODIUM_INCLUDE_DIRS})
|
||||||
|
target_compile_options(UDPConnection PUBLIC ${LIBSODIUM_CFLAGS_OTHER})
|
||||||
|
message(STATUS "libsodium enabled")
|
||||||
|
else()
|
||||||
|
message(STATUS "libsodium not found, UDPC will be compiled without libsodium support")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
if(CMAKE_BUILD_TYPE MATCHES "Debug")
|
if(CMAKE_BUILD_TYPE MATCHES "Debug")
|
||||||
|
|
||||||
|
|
|
@ -38,8 +38,11 @@
|
||||||
#include <sodium.h>
|
#include <sodium.h>
|
||||||
|
|
||||||
#define UDPC_MIN_HEADER_SIZE 20
|
#define UDPC_MIN_HEADER_SIZE 20
|
||||||
#define UDPC_CON_HEADER_SIZE (UDPC_MIN_HEADER_SIZE + crypto_sign_PUBLICKEYBYTES)
|
#define UDPC_CON_HEADER_SIZE (UDPC_MIN_HEADER_SIZE+4)
|
||||||
#define UDPC_FULL_HEADER_SIZE (UDPC_MIN_HEADER_SIZE + crypto_sign_BYTES)
|
#define UDPC_CCL_HEADER_SIZE (UDPC_MIN_HEADER_SIZE+4+crypto_sign_PUBLICKEYBYTES+4)
|
||||||
|
#define UDPC_CSR_HEADER_SIZE (UDPC_MIN_HEADER_SIZE+4+crypto_sign_PUBLICKEYBYTES+crypto_sign_BYTES)
|
||||||
|
#define UDPC_LSFULL_HEADER_SIZE (UDPC_MIN_HEADER_SIZE+1+crypto_sign_BYTES)
|
||||||
|
#define UDPC_NSFULL_HEADER_SIZE (UDPC_MIN_HEADER_SIZE+1)
|
||||||
|
|
||||||
namespace UDPC {
|
namespace UDPC {
|
||||||
|
|
||||||
|
@ -76,8 +79,14 @@ struct IPV6_Hasher {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ConnectionData {
|
struct ConnectionData {
|
||||||
ConnectionData();
|
ConnectionData(bool isUsingLibsodium);
|
||||||
ConnectionData(bool isServer, Context *ctx, UDPC_IPV6_ADDR_TYPE addr, uint32_t scope_id, uint16_t port);
|
ConnectionData(
|
||||||
|
bool isServer,
|
||||||
|
Context *ctx,
|
||||||
|
UDPC_IPV6_ADDR_TYPE addr,
|
||||||
|
uint32_t scope_id,
|
||||||
|
uint16_t port,
|
||||||
|
bool isUsingLibsodium);
|
||||||
|
|
||||||
// copy
|
// copy
|
||||||
ConnectionData(const ConnectionData& other) = delete;
|
ConnectionData(const ConnectionData& other) = delete;
|
||||||
|
@ -96,6 +105,7 @@ struct ConnectionData {
|
||||||
* 3 - initiating connection
|
* 3 - initiating connection
|
||||||
* 4 - is id set
|
* 4 - is id set
|
||||||
* 5 - error initializing keys for public key encryption
|
* 5 - error initializing keys for public key encryption
|
||||||
|
* 6 - using libsodium for header verification
|
||||||
*/
|
*/
|
||||||
std::bitset<8> flags;
|
std::bitset<8> flags;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
@ -120,6 +130,9 @@ struct ConnectionData {
|
||||||
unsigned char sk[crypto_sign_SECRETKEYBYTES];
|
unsigned char sk[crypto_sign_SECRETKEYBYTES];
|
||||||
unsigned char pk[crypto_sign_PUBLICKEYBYTES];
|
unsigned char pk[crypto_sign_PUBLICKEYBYTES];
|
||||||
unsigned char peer_pk[crypto_sign_PUBLICKEYBYTES];
|
unsigned char peer_pk[crypto_sign_PUBLICKEYBYTES];
|
||||||
|
// client - 4 byte string size, rest is string
|
||||||
|
// server - detached signature of size crypto_sign_BYTES
|
||||||
|
std::unique_ptr<char[]> verifyMessage;
|
||||||
}; // struct ConnectionData
|
}; // struct ConnectionData
|
||||||
|
|
||||||
struct Context {
|
struct Context {
|
||||||
|
@ -182,6 +195,7 @@ public:
|
||||||
/*
|
/*
|
||||||
* 0 - is threaded
|
* 0 - is threaded
|
||||||
* 1 - is client
|
* 1 - is client
|
||||||
|
* 2 - libsodium enabled
|
||||||
*/
|
*/
|
||||||
std::bitset<8> flags;
|
std::bitset<8> flags;
|
||||||
std::atomic_bool isAcceptNewConnections;
|
std::atomic_bool isAcceptNewConnections;
|
||||||
|
@ -224,14 +238,13 @@ bool isBigEndian();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* flags:
|
* flags:
|
||||||
* - 0x1 - connect
|
* 0x1 - connect
|
||||||
* - 0x2 - ping
|
* 0x2 - ping
|
||||||
* - 0x4 - no_rec_chk
|
* 0x4 - no_rec_chk
|
||||||
* - 0x8 - resending
|
* 0x8 - resending
|
||||||
*/
|
*/
|
||||||
void preparePacket(char *data, uint32_t protocolID, uint32_t conID,
|
void preparePacket(char *data, uint32_t protocolID, uint32_t conID,
|
||||||
uint32_t rseq, uint32_t ack, uint32_t *seqID, int flags,
|
uint32_t rseq, uint32_t ack, uint32_t *seqID, int flags);
|
||||||
const unsigned char *pk, const unsigned char *sk);
|
|
||||||
|
|
||||||
uint32_t generateConnectionID(Context &ctx);
|
uint32_t generateConnectionID(Context &ctx);
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <ctime>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
|
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
|
||||||
#include <netioapi.h>
|
#include <netioapi.h>
|
||||||
|
@ -76,7 +78,7 @@ bool operator ==(const UDPC_IPV6_ADDR_TYPE& a, const UDPC_IPV6_ADDR_TYPE& b) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
UDPC::ConnectionData::ConnectionData() :
|
UDPC::ConnectionData::ConnectionData(bool isUsingLibsodium) :
|
||||||
flags(),
|
flags(),
|
||||||
id(0),
|
id(0),
|
||||||
lseq(0),
|
lseq(0),
|
||||||
|
@ -98,12 +100,24 @@ rtt(std::chrono::steady_clock::duration::zero())
|
||||||
flags.set(0);
|
flags.set(0);
|
||||||
flags.reset(1);
|
flags.reset(1);
|
||||||
|
|
||||||
|
#ifdef UDPC_LIBSODIUM_ENABLED
|
||||||
|
if(isUsingLibsodium) {
|
||||||
if(sodium_init() >= 0) {
|
if(sodium_init() >= 0) {
|
||||||
crypto_sign_keypair(pk, sk);
|
crypto_sign_keypair(pk, sk);
|
||||||
flags.reset(5);
|
flags.reset(5);
|
||||||
|
flags.set(6);
|
||||||
} else {
|
} else {
|
||||||
flags.set(5);
|
flags.set(5);
|
||||||
|
flags.reset(6);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
flags.reset(5);
|
||||||
|
flags.reset(6);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
flags.reset(5);
|
||||||
|
flags.reset(6);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
UDPC::ConnectionData::ConnectionData(
|
UDPC::ConnectionData::ConnectionData(
|
||||||
|
@ -111,7 +125,8 @@ UDPC::ConnectionData::ConnectionData(
|
||||||
Context *ctx,
|
Context *ctx,
|
||||||
UDPC_IPV6_ADDR_TYPE addr,
|
UDPC_IPV6_ADDR_TYPE addr,
|
||||||
uint32_t scope_id,
|
uint32_t scope_id,
|
||||||
uint16_t port) :
|
uint16_t port,
|
||||||
|
bool isUsingLibsodium) :
|
||||||
flags(),
|
flags(),
|
||||||
id(0),
|
id(0),
|
||||||
lseq(0),
|
lseq(0),
|
||||||
|
@ -139,12 +154,24 @@ rtt(std::chrono::steady_clock::duration::zero())
|
||||||
lseq = 1;
|
lseq = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef UDPC_LIBSODIUM_ENABLED
|
||||||
|
if(isUsingLibsodium) {
|
||||||
if(sodium_init() >= 0) {
|
if(sodium_init() >= 0) {
|
||||||
crypto_sign_keypair(pk, sk);
|
crypto_sign_keypair(pk, sk);
|
||||||
flags.reset(5);
|
flags.reset(5);
|
||||||
|
flags.set(6);
|
||||||
} else {
|
} else {
|
||||||
flags.set(5);
|
flags.set(5);
|
||||||
|
flags.reset(6);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
flags.reset(5);
|
||||||
|
flags.reset(6);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
flags.reset(5);
|
||||||
|
flags.reset(6);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void UDPC::ConnectionData::cleanupSentPkts() {
|
void UDPC::ConnectionData::cleanupSentPkts() {
|
||||||
|
@ -238,7 +265,12 @@ void UDPC::Context::update_impl() {
|
||||||
this,
|
this,
|
||||||
optE.value().conId.addr,
|
optE.value().conId.addr,
|
||||||
optE.value().conId.scope_id,
|
optE.value().conId.scope_id,
|
||||||
optE.value().conId.port);
|
optE.value().conId.port,
|
||||||
|
#ifdef UDPC_LIBSODIUM_ENABLED
|
||||||
|
flags.test(2) && optE.value().v.enableLibSodium != 0);
|
||||||
|
#else
|
||||||
|
false);
|
||||||
|
#endif
|
||||||
if(newCon.flags.test(5)) {
|
if(newCon.flags.test(5)) {
|
||||||
UDPC_CHECK_LOG(this,
|
UDPC_CHECK_LOG(this,
|
||||||
UDPC_LoggingType::UDPC_ERROR,
|
UDPC_LoggingType::UDPC_ERROR,
|
||||||
|
@ -250,6 +282,15 @@ void UDPC::Context::update_impl() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
newCon.sent = std::chrono::steady_clock::now() - UDPC::INIT_PKT_INTERVAL_DT;
|
newCon.sent = std::chrono::steady_clock::now() - UDPC::INIT_PKT_INTERVAL_DT;
|
||||||
|
if(flags.test(2) && newCon.flags.test(6)) {
|
||||||
|
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();
|
||||||
|
newCon.verifyMessage = std::make_unique<char[]>(4 + timeString.size());
|
||||||
|
*((uint32_t*)newCon.verifyMessage.get()) = timeString.size();
|
||||||
|
std::memcpy(newCon.verifyMessage.get() + 4, timeString.c_str(), timeString.size());
|
||||||
|
}
|
||||||
|
|
||||||
if(conMap.find(optE.value().conId) == conMap.end()) {
|
if(conMap.find(optE.value().conId) == conMap.end()) {
|
||||||
conMap.insert(std::make_pair(
|
conMap.insert(std::make_pair(
|
||||||
|
@ -283,7 +324,7 @@ void UDPC::Context::update_impl() {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case UDPC_ET_REQUEST_DISCONNECT:
|
case UDPC_ET_REQUEST_DISCONNECT:
|
||||||
if(optE.value().dropAllWithAddr != 0) {
|
if(optE.value().v.dropAllWithAddr != 0) {
|
||||||
// drop all connections with same address
|
// drop all connections with same address
|
||||||
auto addrConIter = addrConMap.find(optE.value().conId.addr);
|
auto addrConIter = addrConMap.find(optE.value().conId.addr);
|
||||||
if(addrConIter != addrConMap.end()) {
|
if(addrConIter != addrConMap.end()) {
|
||||||
|
@ -513,8 +554,44 @@ void UDPC::Context::update_impl() {
|
||||||
}
|
}
|
||||||
iter->second.sent = now;
|
iter->second.sent = now;
|
||||||
|
|
||||||
std::unique_ptr<char[]> buf = std::make_unique<char[]>(
|
std::unique_ptr<char[]> buf;
|
||||||
UDPC_CON_HEADER_SIZE);
|
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());
|
||||||
|
buf = std::make_unique<char[]>(sendSize);
|
||||||
|
// 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()));
|
||||||
|
// TODO impl presetting a known pubkey of peer
|
||||||
|
#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;
|
||||||
|
buf = std::make_unique<char[]>(sendSize);
|
||||||
|
*((uint32_t*)(buf.get() + 20)) = 0;
|
||||||
|
}
|
||||||
UDPC::preparePacket(
|
UDPC::preparePacket(
|
||||||
buf.get(),
|
buf.get(),
|
||||||
protocolID,
|
protocolID,
|
||||||
|
@ -522,9 +599,7 @@ void UDPC::Context::update_impl() {
|
||||||
0,
|
0,
|
||||||
0xFFFFFFFF,
|
0xFFFFFFFF,
|
||||||
nullptr,
|
nullptr,
|
||||||
0x1,
|
0x1);
|
||||||
iter->second.pk,
|
|
||||||
iter->second.sk);
|
|
||||||
|
|
||||||
UDPC_IPV6_SOCKADDR_TYPE destinationInfo;
|
UDPC_IPV6_SOCKADDR_TYPE destinationInfo;
|
||||||
destinationInfo.sin6_family = AF_INET6;
|
destinationInfo.sin6_family = AF_INET6;
|
||||||
|
@ -535,11 +610,11 @@ void UDPC::Context::update_impl() {
|
||||||
long int sentBytes = sendto(
|
long int sentBytes = sendto(
|
||||||
socketHandle,
|
socketHandle,
|
||||||
buf.get(),
|
buf.get(),
|
||||||
UDPC_CON_HEADER_SIZE,
|
sendSize,
|
||||||
0,
|
0,
|
||||||
(struct sockaddr*) &destinationInfo,
|
(struct sockaddr*) &destinationInfo,
|
||||||
sizeof(UDPC_IPV6_SOCKADDR_TYPE));
|
sizeof(UDPC_IPV6_SOCKADDR_TYPE));
|
||||||
if(sentBytes != UDPC_CON_HEADER_SIZE) {
|
if(sentBytes != sendSize) {
|
||||||
UDPC_CHECK_LOG(this,
|
UDPC_CHECK_LOG(this,
|
||||||
UDPC_LoggingType::UDPC_ERROR,
|
UDPC_LoggingType::UDPC_ERROR,
|
||||||
"Failed to send packet to initiate connection to ",
|
"Failed to send packet to initiate connection to ",
|
||||||
|
@ -550,16 +625,45 @@ void UDPC::Context::update_impl() {
|
||||||
} else {
|
} else {
|
||||||
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_INFO, "Sent initiate connection to ",
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_INFO, "Sent initiate connection to ",
|
||||||
UDPC_atostr((UDPC_HContext)this, iter->first.addr),
|
UDPC_atostr((UDPC_HContext)this, iter->first.addr),
|
||||||
", port = ",
|
", port = ", iter->second.port,
|
||||||
iter->second.port);
|
flags.test(2) && iter->second.flags.test(6) ?
|
||||||
|
", libsodium enabled" : ", libsodium disabled");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// is server, initiate connection to client
|
// is server, initiate connection to client
|
||||||
iter->second.flags.reset(3);
|
iter->second.flags.reset(3);
|
||||||
iter->second.sent = now;
|
iter->second.sent = now;
|
||||||
|
|
||||||
std::unique_ptr<char[]> buf = std::make_unique<char[]>(
|
std::unique_ptr<char[]> buf;
|
||||||
UDPC_CON_HEADER_SIZE);
|
unsigned int sendSize = 0;
|
||||||
|
if(flags.test(2) && iter->second.flags.test(6)) {
|
||||||
|
#ifdef UDPC_LIBSODIUM_ENABLED
|
||||||
|
sendSize = UDPC_CSR_HEADER_SIZE;
|
||||||
|
buf = std::make_unique<char[]>(sendSize);
|
||||||
|
// 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;
|
||||||
|
buf = std::make_unique<char[]>(sendSize);
|
||||||
|
*((uint32_t*)(buf.get() + UDPC_MIN_HEADER_SIZE)) = 0;
|
||||||
|
}
|
||||||
UDPC::preparePacket(
|
UDPC::preparePacket(
|
||||||
buf.get(),
|
buf.get(),
|
||||||
protocolID,
|
protocolID,
|
||||||
|
@ -567,9 +671,7 @@ void UDPC::Context::update_impl() {
|
||||||
iter->second.rseq,
|
iter->second.rseq,
|
||||||
iter->second.ack,
|
iter->second.ack,
|
||||||
&iter->second.lseq,
|
&iter->second.lseq,
|
||||||
0x1,
|
0x1);
|
||||||
iter->second.pk,
|
|
||||||
iter->second.sk);
|
|
||||||
|
|
||||||
UDPC_IPV6_SOCKADDR_TYPE destinationInfo;
|
UDPC_IPV6_SOCKADDR_TYPE destinationInfo;
|
||||||
destinationInfo.sin6_family = AF_INET6;
|
destinationInfo.sin6_family = AF_INET6;
|
||||||
|
@ -580,11 +682,11 @@ void UDPC::Context::update_impl() {
|
||||||
long int sentBytes = sendto(
|
long int sentBytes = sendto(
|
||||||
socketHandle,
|
socketHandle,
|
||||||
buf.get(),
|
buf.get(),
|
||||||
UDPC_CON_HEADER_SIZE,
|
sendSize,
|
||||||
0,
|
0,
|
||||||
(struct sockaddr*) &destinationInfo,
|
(struct sockaddr*) &destinationInfo,
|
||||||
sizeof(UDPC_IPV6_SOCKADDR_TYPE));
|
sizeof(UDPC_IPV6_SOCKADDR_TYPE));
|
||||||
if(sentBytes != UDPC_CON_HEADER_SIZE) {
|
if(sentBytes != sendSize) {
|
||||||
UDPC_CHECK_LOG(this,
|
UDPC_CHECK_LOG(this,
|
||||||
UDPC_LoggingType::UDPC_ERROR,
|
UDPC_LoggingType::UDPC_ERROR,
|
||||||
"Failed to send packet to initiate connection to ",
|
"Failed to send packet to initiate connection to ",
|
||||||
|
@ -593,6 +695,10 @@ void UDPC::Context::update_impl() {
|
||||||
iter->second.port);
|
iter->second.port);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -605,8 +711,17 @@ void UDPC::Context::update_impl() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<char[]> buf = std::make_unique<char[]>(
|
unsigned int sendSize = 0;
|
||||||
UDPC_FULL_HEADER_SIZE);
|
std::unique_ptr<char[]> buf;
|
||||||
|
if(flags.test(2) && iter->second.flags.test(6)) {
|
||||||
|
sendSize = UDPC_LSFULL_HEADER_SIZE;
|
||||||
|
buf = std::make_unique<char[]>(sendSize);
|
||||||
|
*((unsigned char*)(buf.get() + UDPC_MIN_HEADER_SIZE)) = 1;
|
||||||
|
} else {
|
||||||
|
sendSize = UDPC_NSFULL_HEADER_SIZE;
|
||||||
|
buf = std::make_unique<char[]>(sendSize);
|
||||||
|
*((unsigned char*)(buf.get() + UDPC_MIN_HEADER_SIZE)) = 0;
|
||||||
|
}
|
||||||
UDPC::preparePacket(
|
UDPC::preparePacket(
|
||||||
buf.get(),
|
buf.get(),
|
||||||
protocolID,
|
protocolID,
|
||||||
|
@ -614,9 +729,27 @@ void UDPC::Context::update_impl() {
|
||||||
iter->second.rseq,
|
iter->second.rseq,
|
||||||
iter->second.ack,
|
iter->second.ack,
|
||||||
&iter->second.lseq,
|
&iter->second.lseq,
|
||||||
0,
|
0);
|
||||||
iter->second.pk,
|
if(flags.test(2) && iter->second.flags.test(6)) {
|
||||||
iter->second.sk);
|
#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;
|
UDPC_IPV6_SOCKADDR_TYPE destinationInfo;
|
||||||
destinationInfo.sin6_family = AF_INET6;
|
destinationInfo.sin6_family = AF_INET6;
|
||||||
|
@ -630,11 +763,11 @@ void UDPC::Context::update_impl() {
|
||||||
long int sentBytes = sendto(
|
long int sentBytes = sendto(
|
||||||
socketHandle,
|
socketHandle,
|
||||||
buf.get(),
|
buf.get(),
|
||||||
UDPC_FULL_HEADER_SIZE,
|
sendSize,
|
||||||
0,
|
0,
|
||||||
(struct sockaddr*) &destinationInfo,
|
(struct sockaddr*) &destinationInfo,
|
||||||
sizeof(UDPC_IPV6_SOCKADDR_TYPE));
|
sizeof(UDPC_IPV6_SOCKADDR_TYPE));
|
||||||
if(sentBytes != UDPC_FULL_HEADER_SIZE) {
|
if(sentBytes != sendSize) {
|
||||||
UDPC_CHECK_LOG(this,
|
UDPC_CHECK_LOG(this,
|
||||||
UDPC_LoggingType::UDPC_ERROR,
|
UDPC_LoggingType::UDPC_ERROR,
|
||||||
"Failed to send heartbeat packet to ",
|
"Failed to send heartbeat packet to ",
|
||||||
|
@ -651,6 +784,7 @@ void UDPC::Context::update_impl() {
|
||||||
pInfo.sender.port = ntohs(socketInfo.sin6_port);
|
pInfo.sender.port = ntohs(socketInfo.sin6_port);
|
||||||
pInfo.receiver.port = iter->second.port;
|
pInfo.receiver.port = iter->second.port;
|
||||||
*((uint32_t*)(pInfo.data + 8)) = htonl(iter->second.lseq - 1);
|
*((uint32_t*)(pInfo.data + 8)) = htonl(iter->second.lseq - 1);
|
||||||
|
pInfo.data[UDPC_MIN_HEADER_SIZE] = flags.test(2) && iter->second.flags.test(6) ? 1 : 0;
|
||||||
|
|
||||||
iter->second.sentPkts.push_back(std::move(pInfo));
|
iter->second.sentPkts.push_back(std::move(pInfo));
|
||||||
iter->second.cleanupSentPkts();
|
iter->second.cleanupSentPkts();
|
||||||
|
@ -671,7 +805,19 @@ void UDPC::Context::update_impl() {
|
||||||
pInfo = iter->second.sendPkts.front();
|
pInfo = iter->second.sendPkts.front();
|
||||||
iter->second.sendPkts.pop_front();
|
iter->second.sendPkts.pop_front();
|
||||||
}
|
}
|
||||||
std::unique_ptr<char[]> buf = std::make_unique<char[]>(UDPC_FULL_HEADER_SIZE + pInfo.dataSize);
|
|
||||||
|
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;
|
||||||
|
buf = std::make_unique<char[]>(sendSize);
|
||||||
|
*((unsigned char*)(buf.get() + UDPC_MIN_HEADER_SIZE)) = 1;
|
||||||
|
} else {
|
||||||
|
sendSize = UDPC_NSFULL_HEADER_SIZE + pInfo.dataSize;
|
||||||
|
buf = std::make_unique<char[]>(sendSize);
|
||||||
|
*((unsigned char*)(buf.get() + UDPC_MIN_HEADER_SIZE)) = 0;
|
||||||
|
}
|
||||||
|
|
||||||
UDPC::preparePacket(
|
UDPC::preparePacket(
|
||||||
buf.get(),
|
buf.get(),
|
||||||
protocolID,
|
protocolID,
|
||||||
|
@ -679,10 +825,32 @@ void UDPC::Context::update_impl() {
|
||||||
iter->second.rseq,
|
iter->second.rseq,
|
||||||
iter->second.ack,
|
iter->second.ack,
|
||||||
&iter->second.lseq,
|
&iter->second.lseq,
|
||||||
(pInfo.flags & 0x4) | (isResending ? 0x8 : 0),
|
(pInfo.flags & 0x4) | (isResending ? 0x8 : 0));
|
||||||
iter->second.pk,
|
|
||||||
iter->second.sk);
|
if(flags.test(2) && iter->second.flags.test(6)) {
|
||||||
std::memcpy(buf.get() + UDPC_FULL_HEADER_SIZE, pInfo.data, pInfo.dataSize);
|
#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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
UDPC_IPV6_SOCKADDR_TYPE destinationInfo;
|
UDPC_IPV6_SOCKADDR_TYPE destinationInfo;
|
||||||
destinationInfo.sin6_family = AF_INET6;
|
destinationInfo.sin6_family = AF_INET6;
|
||||||
|
@ -696,11 +864,11 @@ void UDPC::Context::update_impl() {
|
||||||
long int sentBytes = sendto(
|
long int sentBytes = sendto(
|
||||||
socketHandle,
|
socketHandle,
|
||||||
buf.get(),
|
buf.get(),
|
||||||
pInfo.dataSize + UDPC_FULL_HEADER_SIZE,
|
sendSize,
|
||||||
0,
|
0,
|
||||||
(struct sockaddr*) &destinationInfo,
|
(struct sockaddr*) &destinationInfo,
|
||||||
sizeof(UDPC_IPV6_SOCKADDR_TYPE));
|
sizeof(UDPC_IPV6_SOCKADDR_TYPE));
|
||||||
if(sentBytes != UDPC_FULL_HEADER_SIZE + pInfo.dataSize) {
|
if(sentBytes != sendSize) {
|
||||||
UDPC_CHECK_LOG(this,
|
UDPC_CHECK_LOG(this,
|
||||||
UDPC_LoggingType::UDPC_ERROR,
|
UDPC_LoggingType::UDPC_ERROR,
|
||||||
"Failed to send packet to ",
|
"Failed to send packet to ",
|
||||||
|
@ -713,9 +881,9 @@ void UDPC::Context::update_impl() {
|
||||||
if((pInfo.flags & 0x4) == 0) {
|
if((pInfo.flags & 0x4) == 0) {
|
||||||
// is check-received, store data in case packet gets lost
|
// is check-received, store data in case packet gets lost
|
||||||
UDPC_PacketInfo sentPInfo = UDPC::get_empty_pinfo();
|
UDPC_PacketInfo sentPInfo = UDPC::get_empty_pinfo();
|
||||||
std::memcpy(sentPInfo.data, buf.get(), UDPC_FULL_HEADER_SIZE + pInfo.dataSize);
|
std::memcpy(sentPInfo.data, buf.get(), sendSize);
|
||||||
sentPInfo.flags = 0;
|
sentPInfo.flags = 0;
|
||||||
sentPInfo.dataSize = UDPC_FULL_HEADER_SIZE + pInfo.dataSize;
|
sentPInfo.dataSize = sendSize;
|
||||||
sentPInfo.sender.addr = in6addr_loopback;
|
sentPInfo.sender.addr = in6addr_loopback;
|
||||||
sentPInfo.receiver.addr = iter->first.addr;
|
sentPInfo.receiver.addr = iter->first.addr;
|
||||||
sentPInfo.sender.port = ntohs(socketInfo.sin6_port);
|
sentPInfo.sender.port = ntohs(socketInfo.sin6_port);
|
||||||
|
@ -809,7 +977,7 @@ void UDPC::Context::update_impl() {
|
||||||
bool isResending = conID & UDPC_ID_RESENDING;
|
bool isResending = conID & UDPC_ID_RESENDING;
|
||||||
conID &= 0x0FFFFFFF;
|
conID &= 0x0FFFFFFF;
|
||||||
|
|
||||||
if(isConnect && bytes != UDPC_CON_HEADER_SIZE) {
|
if(isConnect && bytes < (int)(UDPC_CON_HEADER_SIZE)) {
|
||||||
// invalid packet size
|
// invalid packet size
|
||||||
UDPC_CHECK_LOG(this,
|
UDPC_CHECK_LOG(this,
|
||||||
UDPC_LoggingType::UDPC_VERBOSE,
|
UDPC_LoggingType::UDPC_VERBOSE,
|
||||||
|
@ -819,7 +987,7 @@ void UDPC::Context::update_impl() {
|
||||||
ntohs(receivedData.sin6_port),
|
ntohs(receivedData.sin6_port),
|
||||||
", ignoring");
|
", ignoring");
|
||||||
return;
|
return;
|
||||||
} else if (!isConnect && bytes < (int)UDPC_FULL_HEADER_SIZE) {
|
} else if (!isConnect && bytes < (int)UDPC_NSFULL_HEADER_SIZE) {
|
||||||
// packet is too small
|
// packet is too small
|
||||||
UDPC_CHECK_LOG(this,
|
UDPC_CHECK_LOG(this,
|
||||||
UDPC_LoggingType::UDPC_VERBOSE,
|
UDPC_LoggingType::UDPC_VERBOSE,
|
||||||
|
@ -833,12 +1001,56 @@ void UDPC::Context::update_impl() {
|
||||||
|
|
||||||
UDPC_ConnectionId identifier{receivedData.sin6_addr, receivedData.sin6_scope_id, ntohs(receivedData.sin6_port)};
|
UDPC_ConnectionId identifier{receivedData.sin6_addr, receivedData.sin6_scope_id, ntohs(receivedData.sin6_port)};
|
||||||
|
|
||||||
if(isConnect && isAcceptNewConnections.load()) {
|
uint32_t pktType = 0;
|
||||||
|
if(isConnect) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isConnect) {
|
||||||
// is connect packet and is accepting new connections
|
// is connect packet and is accepting new connections
|
||||||
if(!flags.test(1)
|
if(!flags.test(1)
|
||||||
&& conMap.find(identifier) == conMap.end()) {
|
&& conMap.find(identifier) == conMap.end()
|
||||||
|
&& isAcceptNewConnections.load()) {
|
||||||
// is receiving as server, connection did not already exist
|
// is receiving as server, connection did not already exist
|
||||||
UDPC::ConnectionData newConnection(true, this, receivedData.sin6_addr, receivedData.sin6_scope_id, ntohs(receivedData.sin6_port));
|
UDPC::ConnectionData newConnection(
|
||||||
|
true,
|
||||||
|
this,
|
||||||
|
receivedData.sin6_addr,
|
||||||
|
receivedData.sin6_scope_id,
|
||||||
|
ntohs(receivedData.sin6_port),
|
||||||
|
#ifdef UDPC_LIBSODIUM_ENABLED
|
||||||
|
pktType == 1 && flags.test(2));
|
||||||
|
#else
|
||||||
|
false);
|
||||||
|
#endif
|
||||||
if(newConnection.flags.test(5)) {
|
if(newConnection.flags.test(5)) {
|
||||||
UDPC_CHECK_LOG(this,
|
UDPC_CHECK_LOG(this,
|
||||||
UDPC_LoggingType::UDPC_ERROR,
|
UDPC_LoggingType::UDPC_ERROR,
|
||||||
|
@ -849,15 +1061,34 @@ void UDPC::Context::update_impl() {
|
||||||
ntohs(receivedData.sin6_port));
|
ntohs(receivedData.sin6_port));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::memcpy(newConnection.peer_pk, recvBuf + UDPC_MIN_HEADER_SIZE,
|
if(pktType == 1 && flags.test(2)) {
|
||||||
|
#ifdef UDPC_LIBSODIUM_ENABLED
|
||||||
|
std::memcpy(
|
||||||
|
newConnection.peer_pk,
|
||||||
|
recvBuf + UDPC_MIN_HEADER_SIZE + 4,
|
||||||
crypto_sign_PUBLICKEYBYTES);
|
crypto_sign_PUBLICKEYBYTES);
|
||||||
|
newConnection.verifyMessage = std::make_unique<char[]>(crypto_sign_BYTES);
|
||||||
|
crypto_sign_detached(
|
||||||
|
(unsigned char*)newConnection.verifyMessage.get(),
|
||||||
|
nullptr,
|
||||||
|
(unsigned char*)(recvBuf + UDPC_MIN_HEADER_SIZE + 4 + crypto_sign_PUBLICKEYBYTES + 4),
|
||||||
|
ntohl(*((uint32_t*)(recvBuf + UDPC_MIN_HEADER_SIZE + 4 + crypto_sign_PUBLICKEYBYTES))), newConnection.sk);
|
||||||
|
#else
|
||||||
|
assert(!"libsodium disabled, invalid state");
|
||||||
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
|
||||||
|
"libsodium is disabled, cannot process received packet");
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
UDPC_CHECK_LOG(this,
|
UDPC_CHECK_LOG(this,
|
||||||
UDPC_LoggingType::UDPC_INFO,
|
UDPC_LoggingType::UDPC_INFO,
|
||||||
"Establishing connection with client ",
|
"Establishing connection with client ",
|
||||||
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
|
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
|
||||||
", port = ",
|
", port = ",
|
||||||
ntohs(receivedData.sin6_port),
|
ntohs(receivedData.sin6_port),
|
||||||
", giving client id = ", newConnection.id);
|
", giving client id = ", newConnection.id,
|
||||||
|
pktType == 1 && flags.test(2) ?
|
||||||
|
", libsodium enabled" : ", libsodium disabled");
|
||||||
|
|
||||||
idMap.insert(std::make_pair(newConnection.id, identifier));
|
idMap.insert(std::make_pair(newConnection.id, identifier));
|
||||||
conMap.insert(std::make_pair(identifier, std::move(newConnection)));
|
conMap.insert(std::make_pair(identifier, std::move(newConnection)));
|
||||||
|
@ -883,20 +1114,50 @@ void UDPC::Context::update_impl() {
|
||||||
// is client
|
// is client
|
||||||
auto iter = conMap.find(identifier);
|
auto iter = conMap.find(identifier);
|
||||||
if(iter == conMap.end() || !iter->second.flags.test(3)) {
|
if(iter == conMap.end() || !iter->second.flags.test(3)) {
|
||||||
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(pktType == 2 && flags.test(2) && iter->second.flags.test(6)) {
|
||||||
|
#ifdef UDPC_LIBSODIUM_ENABLED
|
||||||
|
std::memcpy(iter->second.peer_pk, recvBuf + UDPC_MIN_HEADER_SIZE + 4,
|
||||||
|
crypto_sign_PUBLICKEYBYTES);
|
||||||
|
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");
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
} else if(pktType == 0 && iter->second.flags.test(6)) {
|
||||||
|
iter->second.flags.reset(6);
|
||||||
|
}
|
||||||
|
|
||||||
iter->second.flags.reset(3);
|
iter->second.flags.reset(3);
|
||||||
iter->second.id = conID;
|
iter->second.id = conID;
|
||||||
iter->second.flags.set(4);
|
iter->second.flags.set(4);
|
||||||
std::memcpy(iter->second.peer_pk, recvBuf + UDPC_MIN_HEADER_SIZE,
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_INFO,
|
||||||
crypto_sign_PUBLICKEYBYTES);
|
|
||||||
UDPC_CHECK_LOG(this,
|
|
||||||
UDPC_LoggingType::UDPC_INFO,
|
|
||||||
"Established connection with server ",
|
"Established connection with server ",
|
||||||
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
|
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
|
||||||
", port = ",
|
", port = ",
|
||||||
ntohs(receivedData.sin6_port),
|
ntohs(receivedData.sin6_port),
|
||||||
", got id = ", conID);
|
", got id = ", conID,
|
||||||
|
flags.test(2) && iter->second.flags.test(6) ?
|
||||||
|
", libsodium enabled" : ", libsodium disabled");
|
||||||
if(isReceivingEvents.load()) {
|
if(isReceivingEvents.load()) {
|
||||||
externalEvents.push(UDPC_Event{
|
externalEvents.push(UDPC_Event{
|
||||||
UDPC_ET_CONNECTED,
|
UDPC_ET_CONNECTED,
|
||||||
|
@ -915,9 +1176,11 @@ void UDPC::Context::update_impl() {
|
||||||
iter->second.flags.set(0);
|
iter->second.flags.set(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(pktType == 1) {
|
||||||
|
#ifdef UDPC_LIBSODIUM_ENABLED
|
||||||
// verify signature of header
|
// verify signature of header
|
||||||
if(crypto_sign_verify_detached(
|
if(crypto_sign_verify_detached(
|
||||||
(unsigned char*)(recvBuf + UDPC_MIN_HEADER_SIZE),
|
(unsigned char*)(recvBuf + UDPC_MIN_HEADER_SIZE + 1),
|
||||||
(unsigned char*)recvBuf,
|
(unsigned char*)recvBuf,
|
||||||
UDPC_MIN_HEADER_SIZE,
|
UDPC_MIN_HEADER_SIZE,
|
||||||
iter->second.peer_pk) != 0) {
|
iter->second.peer_pk) != 0) {
|
||||||
|
@ -931,6 +1194,13 @@ void UDPC::Context::update_impl() {
|
||||||
", ignoring");
|
", ignoring");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
assert(!"libsodium disabled, invalid state");
|
||||||
|
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
|
||||||
|
"libsodium is disabled, cannot process received packet");
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// packet is valid
|
// packet is valid
|
||||||
UDPC_CHECK_LOG(this,
|
UDPC_CHECK_LOG(this,
|
||||||
|
@ -991,7 +1261,9 @@ void UDPC::Context::update_impl() {
|
||||||
&& "Every entry in sentPkts must have a corresponding entry in sentInfoMap");
|
&& "Every entry in sentPkts must have a corresponding entry in sentInfoMap");
|
||||||
auto duration = now - sentInfoIter->second->sentTime;
|
auto duration = now - sentInfoIter->second->sentTime;
|
||||||
if(duration > UDPC::PACKET_TIMEOUT_TIME) {
|
if(duration > UDPC::PACKET_TIMEOUT_TIME) {
|
||||||
if(sentIter->dataSize <= UDPC_FULL_HEADER_SIZE) {
|
bool pktSigned = sentIter->data[UDPC_MIN_HEADER_SIZE] == 1;
|
||||||
|
if((pktSigned && sentIter->dataSize <= UDPC_LSFULL_HEADER_SIZE)
|
||||||
|
|| (!pktSigned && sentIter->dataSize <= UDPC_NSFULL_HEADER_SIZE)) {
|
||||||
UDPC_CHECK_LOG(this,
|
UDPC_CHECK_LOG(this,
|
||||||
UDPC_LoggingType::UDPC_VERBOSE,
|
UDPC_LoggingType::UDPC_VERBOSE,
|
||||||
"Timed out packet has no payload (probably "
|
"Timed out packet has no payload (probably "
|
||||||
|
@ -1001,8 +1273,17 @@ void UDPC::Context::update_impl() {
|
||||||
}
|
}
|
||||||
|
|
||||||
UDPC_PacketInfo resendingData = UDPC::get_empty_pinfo();
|
UDPC_PacketInfo resendingData = UDPC::get_empty_pinfo();
|
||||||
resendingData.dataSize = sentIter->dataSize - UDPC_FULL_HEADER_SIZE;
|
if(pktSigned) {
|
||||||
std::memcpy(resendingData.data, sentIter->data + UDPC_FULL_HEADER_SIZE, resendingData.dataSize);
|
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);
|
||||||
|
}
|
||||||
resendingData.flags = 0;
|
resendingData.flags = 0;
|
||||||
iter->second.priorityPkts.push_back(resendingData);
|
iter->second.priorityPkts.push_back(resendingData);
|
||||||
}
|
}
|
||||||
|
@ -1068,7 +1349,8 @@ void UDPC::Context::update_impl() {
|
||||||
"Received packet is out of order");
|
"Received packet is out of order");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bytes > (int)UDPC_FULL_HEADER_SIZE) {
|
if((pktType == 0 && bytes > (int)UDPC_NSFULL_HEADER_SIZE)
|
||||||
|
| (pktType == 1 && bytes > (int)UDPC_LSFULL_HEADER_SIZE)) {
|
||||||
UDPC_PacketInfo recPktInfo = UDPC::get_empty_pinfo();
|
UDPC_PacketInfo recPktInfo = UDPC::get_empty_pinfo();
|
||||||
std::memcpy(recPktInfo.data, recvBuf, bytes);
|
std::memcpy(recPktInfo.data, recvBuf, bytes);
|
||||||
recPktInfo.dataSize = bytes;
|
recPktInfo.dataSize = bytes;
|
||||||
|
@ -1083,7 +1365,7 @@ void UDPC::Context::update_impl() {
|
||||||
recPktInfo.receiver.port = ntohs(socketInfo.sin6_port);
|
recPktInfo.receiver.port = ntohs(socketInfo.sin6_port);
|
||||||
|
|
||||||
receivedPkts.push(recPktInfo);
|
receivedPkts.push(recPktInfo);
|
||||||
} else if(bytes == UDPC_FULL_HEADER_SIZE) {
|
} else {
|
||||||
UDPC_CHECK_LOG(this,
|
UDPC_CHECK_LOG(this,
|
||||||
UDPC_LoggingType::UDPC_VERBOSE,
|
UDPC_LoggingType::UDPC_VERBOSE,
|
||||||
"Received packet has no payload (probably heartbeat packet)");
|
"Received packet has no payload (probably heartbeat packet)");
|
||||||
|
@ -1118,8 +1400,7 @@ bool UDPC::isBigEndian() {
|
||||||
|
|
||||||
void UDPC::preparePacket(
|
void UDPC::preparePacket(
|
||||||
char *data, uint32_t protocolID, uint32_t conID, uint32_t rseq,
|
char *data, uint32_t protocolID, uint32_t conID, uint32_t rseq,
|
||||||
uint32_t ack, uint32_t *seqID, int flags,
|
uint32_t ack, uint32_t *seqID, int flags) {
|
||||||
const unsigned char *pk, const unsigned char *sk) {
|
|
||||||
uint32_t temp;
|
uint32_t temp;
|
||||||
|
|
||||||
temp = htonl(protocolID);
|
temp = htonl(protocolID);
|
||||||
|
@ -1142,17 +1423,6 @@ void UDPC::preparePacket(
|
||||||
std::memcpy(data + 12, &temp, 4);
|
std::memcpy(data + 12, &temp, 4);
|
||||||
temp = htonl(ack);
|
temp = htonl(ack);
|
||||||
std::memcpy(data + 16, &temp, 4);
|
std::memcpy(data + 16, &temp, 4);
|
||||||
|
|
||||||
if((flags & 0x1) != 0) {
|
|
||||||
std::memcpy(data + UDPC_MIN_HEADER_SIZE, pk, crypto_sign_PUBLICKEYBYTES);
|
|
||||||
} else {
|
|
||||||
crypto_sign_detached(
|
|
||||||
(unsigned char*)(data + UDPC_MIN_HEADER_SIZE), // destination of detached sig
|
|
||||||
nullptr, // unused length, assume max
|
|
||||||
(unsigned char*)data, // header to sign
|
|
||||||
UDPC_MIN_HEADER_SIZE, // size of header
|
|
||||||
sk); // secret key
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t UDPC::generateConnectionID(Context &ctx) {
|
uint32_t UDPC::generateConnectionID(Context &ctx) {
|
||||||
|
@ -1233,19 +1503,32 @@ UDPC_ConnectionId UDPC_create_id_easy(const char *addrString, uint16_t port) {
|
||||||
return conId;
|
return conId;
|
||||||
}
|
}
|
||||||
|
|
||||||
UDPC_HContext UDPC_init(UDPC_ConnectionId listenId, int isClient) {
|
UDPC_HContext UDPC_init(UDPC_ConnectionId listenId, int isClient, int isUsingLibsodium) {
|
||||||
UDPC::Context *ctx = new UDPC::Context(false);
|
UDPC::Context *ctx = new UDPC::Context(false);
|
||||||
ctx->flags.set(1, isClient != 0);
|
ctx->flags.set(1, isClient != 0);
|
||||||
|
|
||||||
UDPC_CHECK_LOG(ctx, UDPC_LoggingType::UDPC_INFO, "Got listen addr ",
|
UDPC_CHECK_LOG(ctx, UDPC_LoggingType::UDPC_INFO, "Got listen addr ",
|
||||||
UDPC_atostr((UDPC_HContext)ctx, listenId.addr));
|
UDPC_atostr((UDPC_HContext)ctx, listenId.addr));
|
||||||
|
|
||||||
|
if(isUsingLibsodium) {
|
||||||
|
#ifdef UDPC_LIBSODIUM_ENABLED
|
||||||
// initialize libsodium
|
// initialize libsodium
|
||||||
if(sodium_init() < 0) {
|
if(sodium_init() < 0) {
|
||||||
UDPC_CHECK_LOG(ctx, UDPC_LoggingType::UDPC_ERROR,
|
UDPC_CHECK_LOG(ctx, UDPC_LoggingType::UDPC_ERROR,
|
||||||
"Failed to initialize libsodium");
|
"Failed to initialize libsodium");
|
||||||
delete ctx;
|
delete ctx;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
} else {
|
||||||
|
ctx->flags.set(2);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
UDPC_CHECK_LOG(ctx, UDPC_LoggingType::UDPC_ERROR,
|
||||||
|
"Cannot use libsodium, UDPC was compiled without libsodium support");
|
||||||
|
delete ctx;
|
||||||
|
return nullptr;
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
ctx->flags.reset(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
|
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
|
||||||
|
@ -1330,8 +1613,8 @@ UDPC_HContext UDPC_init(UDPC_ConnectionId listenId, int isClient) {
|
||||||
}
|
}
|
||||||
|
|
||||||
UDPC_HContext UDPC_init_threaded_update(UDPC_ConnectionId listenId,
|
UDPC_HContext UDPC_init_threaded_update(UDPC_ConnectionId listenId,
|
||||||
int isClient) {
|
int isClient, int isUsingLibsodium) {
|
||||||
UDPC::Context *ctx = (UDPC::Context *)UDPC_init(listenId, isClient);
|
UDPC::Context *ctx = (UDPC::Context *)UDPC_init(listenId, isClient, isUsingLibsodium);
|
||||||
if(!ctx) {
|
if(!ctx) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -1345,8 +1628,10 @@ UDPC_HContext UDPC_init_threaded_update(UDPC_ConnectionId listenId,
|
||||||
}
|
}
|
||||||
|
|
||||||
UDPC_HContext UDPC_init_threaded_update_ms(
|
UDPC_HContext UDPC_init_threaded_update_ms(
|
||||||
UDPC_ConnectionId listenId, int isClient, int updateMS) {
|
UDPC_ConnectionId listenId,
|
||||||
UDPC::Context *ctx = (UDPC::Context *)UDPC_init(listenId, isClient);
|
int isClient,int updateMS, int isUsingLibsodium) {
|
||||||
|
UDPC::Context *ctx = (UDPC::Context *)UDPC_init(
|
||||||
|
listenId, isClient, isUsingLibsodium);
|
||||||
if(!ctx) {
|
if(!ctx) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -1389,13 +1674,20 @@ void UDPC_update(UDPC_HContext ctx) {
|
||||||
c->update_impl();
|
c->update_impl();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UDPC_client_initiate_connection(UDPC_HContext ctx, UDPC_ConnectionId connectionId) {
|
void UDPC_client_initiate_connection(UDPC_HContext ctx, UDPC_ConnectionId connectionId, int enableLibSodium) {
|
||||||
UDPC::Context *c = UDPC::verifyContext(ctx);
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
||||||
if(!c || !c->flags.test(1)) {
|
if(!c || !c->flags.test(1)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#ifndef UDPC_LIBSODIUM_ENABLED
|
||||||
|
if(enableLibSodium) {
|
||||||
|
UDPC_CHECK_LOG(c, UDPC_LoggingType::UDPC_ERROR,
|
||||||
|
"Cannot enable libsodium, UDPC was compiled without libsodium");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
c->internalEvents.push(UDPC_Event{UDPC_ET_REQUEST_CONNECT, connectionId, false});
|
c->internalEvents.push(UDPC_Event{UDPC_ET_REQUEST_CONNECT, connectionId, enableLibSodium});
|
||||||
}
|
}
|
||||||
|
|
||||||
void UDPC_queue_send(UDPC_HContext ctx, UDPC_ConnectionId destinationId,
|
void UDPC_queue_send(UDPC_HContext ctx, UDPC_ConnectionId destinationId,
|
||||||
|
|
|
@ -54,6 +54,12 @@
|
||||||
#define UDPC_PACKET_MAX_SIZE 8192
|
#define UDPC_PACKET_MAX_SIZE 8192
|
||||||
#define UDPC_DEFAULT_PROTOCOL_ID 1357924680 // 0x50f04948
|
#define UDPC_DEFAULT_PROTOCOL_ID 1357924680 // 0x50f04948
|
||||||
|
|
||||||
|
#ifndef UDPC_LIBSODIUM_ENABLED
|
||||||
|
# define crypto_sign_PUBLICKEYBYTES 1
|
||||||
|
# define crypto_sign_SECRETKEYBYTES 1
|
||||||
|
# define crypto_sign_BYTES 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -101,7 +107,10 @@ typedef enum {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
UDPC_EventType type;
|
UDPC_EventType type;
|
||||||
UDPC_ConnectionId conId;
|
UDPC_ConnectionId conId;
|
||||||
|
union Value {
|
||||||
int dropAllWithAddr;
|
int dropAllWithAddr;
|
||||||
|
int enableLibSodium;
|
||||||
|
} v;
|
||||||
} UDPC_Event;
|
} UDPC_Event;
|
||||||
|
|
||||||
/// port should be in native byte order (not network/big-endian)
|
/// port should be in native byte order (not network/big-endian)
|
||||||
|
@ -113,20 +122,22 @@ UDPC_ConnectionId UDPC_create_id_anyaddr(uint16_t port);
|
||||||
|
|
||||||
UDPC_ConnectionId UDPC_create_id_easy(const char *addrString, uint16_t port);
|
UDPC_ConnectionId UDPC_create_id_easy(const char *addrString, uint16_t port);
|
||||||
|
|
||||||
UDPC_HContext UDPC_init(UDPC_ConnectionId listenId, int isClient);
|
UDPC_HContext UDPC_init(UDPC_ConnectionId listenId, int isClient, int isUsingLibsodium);
|
||||||
UDPC_HContext UDPC_init_threaded_update(
|
UDPC_HContext UDPC_init_threaded_update(
|
||||||
UDPC_ConnectionId listenId,
|
UDPC_ConnectionId listenId,
|
||||||
int isClient);
|
int isClient,
|
||||||
|
int isUsingLibsodium);
|
||||||
UDPC_HContext UDPC_init_threaded_update_ms(
|
UDPC_HContext UDPC_init_threaded_update_ms(
|
||||||
UDPC_ConnectionId listenId,
|
UDPC_ConnectionId listenId,
|
||||||
int isClient,
|
int isClient,
|
||||||
int updateMS);
|
int updateMS,
|
||||||
|
int isUsingLibsodium);
|
||||||
|
|
||||||
void UDPC_destroy(UDPC_HContext ctx);
|
void UDPC_destroy(UDPC_HContext ctx);
|
||||||
|
|
||||||
void UDPC_update(UDPC_HContext ctx);
|
void UDPC_update(UDPC_HContext ctx);
|
||||||
|
|
||||||
void UDPC_client_initiate_connection(UDPC_HContext ctx, UDPC_ConnectionId connectionId);
|
void UDPC_client_initiate_connection(UDPC_HContext ctx, UDPC_ConnectionId connectionId, int enableLibSodium);
|
||||||
|
|
||||||
void UDPC_queue_send(UDPC_HContext ctx, UDPC_ConnectionId destinationId,
|
void UDPC_queue_send(UDPC_HContext ctx, UDPC_ConnectionId destinationId,
|
||||||
int isChecked, void *data, uint32_t size);
|
int isChecked, void *data, uint32_t size);
|
||||||
|
|
|
@ -18,6 +18,7 @@ void usage() {
|
||||||
puts("-n - do not add payload to packets");
|
puts("-n - do not add payload to packets");
|
||||||
puts("-l (silent|error|warning|info|verbose|debug) - log level, default debug");
|
puts("-l (silent|error|warning|info|verbose|debug) - log level, default debug");
|
||||||
puts("-e - enable receiving events");
|
puts("-e - enable receiving events");
|
||||||
|
puts("-ls - enable libsodium");
|
||||||
}
|
}
|
||||||
|
|
||||||
void sleep_seconds(unsigned int seconds) {
|
void sleep_seconds(unsigned int seconds) {
|
||||||
|
@ -43,6 +44,7 @@ int main(int argc, char **argv) {
|
||||||
int noPayload = 0;
|
int noPayload = 0;
|
||||||
UDPC_LoggingType logLevel = UDPC_DEBUG;
|
UDPC_LoggingType logLevel = UDPC_DEBUG;
|
||||||
int isReceivingEvents = 0;
|
int isReceivingEvents = 0;
|
||||||
|
int isLibSodiumEnabled = 0;
|
||||||
while(argc > 0) {
|
while(argc > 0) {
|
||||||
if(strcmp(argv[0], "-c") == 0) {
|
if(strcmp(argv[0], "-c") == 0) {
|
||||||
isClient = 1;
|
isClient = 1;
|
||||||
|
@ -90,6 +92,9 @@ int main(int argc, char **argv) {
|
||||||
} else if(strcmp(argv[0], "-e") == 0) {
|
} else if(strcmp(argv[0], "-e") == 0) {
|
||||||
isReceivingEvents = 1;
|
isReceivingEvents = 1;
|
||||||
puts("Enabled isReceivingEvents");
|
puts("Enabled isReceivingEvents");
|
||||||
|
} else if(strcmp(argv[0], "-ls") == 0) {
|
||||||
|
isLibSodiumEnabled = 1;
|
||||||
|
puts("Enabled libsodium");
|
||||||
} else {
|
} else {
|
||||||
printf("ERROR: invalid argument \"%s\"\n", argv[0]);
|
printf("ERROR: invalid argument \"%s\"\n", argv[0]);
|
||||||
usage();
|
usage();
|
||||||
|
@ -99,6 +104,10 @@ int main(int argc, char **argv) {
|
||||||
--argc; ++argv;
|
--argc; ++argv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(isLibSodiumEnabled == 0) {
|
||||||
|
puts("Disabled libsodium");
|
||||||
|
}
|
||||||
|
|
||||||
if(!listenAddr) {
|
if(!listenAddr) {
|
||||||
puts("ERROR: listenAddr was not specified");
|
puts("ERROR: listenAddr was not specified");
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -123,7 +132,7 @@ int main(int argc, char **argv) {
|
||||||
if(isClient) {
|
if(isClient) {
|
||||||
connectionId = UDPC_create_id_easy(connectionAddr, atoi(connectionPort));
|
connectionId = UDPC_create_id_easy(connectionAddr, atoi(connectionPort));
|
||||||
}
|
}
|
||||||
UDPC_HContext context = UDPC_init_threaded_update(listenId, isClient);
|
UDPC_HContext context = UDPC_init_threaded_update(listenId, isClient, isLibSodiumEnabled);
|
||||||
if(!context) {
|
if(!context) {
|
||||||
puts("ERROR: context is NULL");
|
puts("ERROR: context is NULL");
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -142,7 +151,7 @@ int main(int argc, char **argv) {
|
||||||
while(1) {
|
while(1) {
|
||||||
sleep_seconds(1);
|
sleep_seconds(1);
|
||||||
if(isClient && UDPC_has_connection(context, connectionId) == 0) {
|
if(isClient && UDPC_has_connection(context, connectionId) == 0) {
|
||||||
UDPC_client_initiate_connection(context, connectionId);
|
UDPC_client_initiate_connection(context, connectionId, isLibSodiumEnabled);
|
||||||
}
|
}
|
||||||
if(!noPayload) {
|
if(!noPayload) {
|
||||||
list = UDPC_get_list_connected(context, &temp);
|
list = UDPC_get_list_connected(context, &temp);
|
||||||
|
|
Loading…
Reference in a new issue