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:
Stephen Seo 2019-11-18 17:37:03 +09:00
parent f2b4672318
commit 4cfe35ecd1
5 changed files with 456 additions and 121 deletions

View file

@ -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")

View file

@ -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);

View file

@ -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);
if(sodium_init() >= 0) { #ifdef UDPC_LIBSODIUM_ENABLED
crypto_sign_keypair(pk, sk); if(isUsingLibsodium) {
flags.reset(5); if(sodium_init() >= 0) {
crypto_sign_keypair(pk, sk);
flags.reset(5);
flags.set(6);
} else {
flags.set(5);
flags.reset(6);
}
} else { } else {
flags.set(5); 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;
} }
if(sodium_init() >= 0) { #ifdef UDPC_LIBSODIUM_ENABLED
crypto_sign_keypair(pk, sk); if(isUsingLibsodium) {
flags.reset(5); if(sodium_init() >= 0) {
crypto_sign_keypair(pk, sk);
flags.reset(5);
flags.set(6);
} else {
flags.set(5);
flags.reset(6);
}
} else { } else {
flags.set(5); 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)) {
crypto_sign_PUBLICKEYBYTES); #ifdef UDPC_LIBSODIUM_ENABLED
std::memcpy(
newConnection.peer_pk,
recvBuf + UDPC_MIN_HEADER_SIZE + 4,
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,21 +1176,30 @@ void UDPC::Context::update_impl() {
iter->second.flags.set(0); iter->second.flags.set(0);
} }
// verify signature of header if(pktType == 1) {
if(crypto_sign_verify_detached( #ifdef UDPC_LIBSODIUM_ENABLED
(unsigned char*)(recvBuf + UDPC_MIN_HEADER_SIZE), // verify signature of header
(unsigned char*)recvBuf, if(crypto_sign_verify_detached(
UDPC_MIN_HEADER_SIZE, (unsigned char*)(recvBuf + UDPC_MIN_HEADER_SIZE + 1),
iter->second.peer_pk) != 0) { (unsigned char*)recvBuf,
UDPC_CHECK_LOG( UDPC_MIN_HEADER_SIZE,
this, iter->second.peer_pk) != 0) {
UDPC_LoggingType::UDPC_INFO, UDPC_CHECK_LOG(
"Failed to verify received packet from", this,
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr), UDPC_LoggingType::UDPC_INFO,
", port = ", "Failed to verify received packet from",
ntohs(receivedData.sin6_port), UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
", ignoring"); ", 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");
return; return;
#endif
} }
// packet is valid // packet is valid
@ -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));
// initialize libsodium if(isUsingLibsodium) {
if(sodium_init() < 0) { #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
UDPC_CHECK_LOG(ctx, UDPC_LoggingType::UDPC_ERROR, UDPC_CHECK_LOG(ctx, UDPC_LoggingType::UDPC_ERROR,
"Failed to initialize libsodium"); "Cannot use libsodium, UDPC was compiled without libsodium support");
delete ctx; delete ctx;
return nullptr; 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,

View file

@ -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;
int dropAllWithAddr; union Value {
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);

View file

@ -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);