Fixes and improvements (add use of TSLQueue)

Replace "unsigned long long" in TSLQueue with "unsigned long" to keep
compatibility with C.

Add top_and_pop_and_rsize() to TSLQueue.

Fix log levels in UDPC.

Replace TSQueue with TSLQueue in UDPC_Context.
Also fix NetworkTest with TSLQueue related changes.
This commit is contained in:
Stephen Seo 2019-11-06 14:35:16 +09:00
parent 742db465dd
commit 7c889eee6a
5 changed files with 145 additions and 89 deletions

View file

@ -30,10 +30,11 @@ class TSLQueue {
bool pop(); bool pop();
std::optional<T> top_and_pop(); std::optional<T> top_and_pop();
std::optional<T> top_and_pop_and_empty(bool *isEmpty); std::optional<T> top_and_pop_and_empty(bool *isEmpty);
std::optional<T> top_and_pop_and_rsize(unsigned long *rsize);
void clear(); void clear();
bool empty(); bool empty();
unsigned long long size(); unsigned long size();
private: private:
struct TSLQNode { struct TSLQNode {
@ -63,7 +64,7 @@ class TSLQueue {
public: public:
TSLQIter(std::mutex &mutex, TSLQIter(std::mutex &mutex,
std::weak_ptr<TSLQNode> currentNode, std::weak_ptr<TSLQNode> currentNode,
unsigned long long *msize); unsigned long *msize);
~TSLQIter(); ~TSLQIter();
std::optional<T> current(); std::optional<T> current();
@ -74,7 +75,7 @@ class TSLQueue {
private: private:
std::lock_guard<std::mutex> lock; std::lock_guard<std::mutex> lock;
std::weak_ptr<TSLQNode> currentNode; std::weak_ptr<TSLQNode> currentNode;
unsigned long long *const msize; unsigned long *const msize;
}; };
@ -85,7 +86,7 @@ class TSLQueue {
std::mutex mutex; std::mutex mutex;
std::shared_ptr<TSLQNode> head; std::shared_ptr<TSLQNode> head;
std::shared_ptr<TSLQNode> tail; std::shared_ptr<TSLQNode> tail;
unsigned long long msize; unsigned long msize;
}; };
template <typename T> template <typename T>
@ -243,6 +244,31 @@ std::optional<T> TSLQueue<T>::top_and_pop_and_empty(bool *isEmpty) {
return ret; return ret;
} }
template <typename T>
std::optional<T> TSLQueue<T>::top_and_pop_and_rsize(unsigned long *rsize) {
std::optional<T> ret = std::nullopt;
std::lock_guard lock(mutex);
if(head->next == tail) {
if(rsize) {
*rsize = 0;
}
} else {
assert(head->next->data);
ret = *head->next->data.get();
auto& newNext = head->next->next;
newNext->prev = head;
head->next = newNext;
assert(msize > 0);
--msize;
if(rsize) {
*rsize = msize;
}
}
return ret;
}
template <typename T> template <typename T>
void TSLQueue<T>::clear() { void TSLQueue<T>::clear() {
std::lock_guard lock(mutex); std::lock_guard lock(mutex);
@ -259,7 +285,7 @@ bool TSLQueue<T>::empty() {
} }
template <typename T> template <typename T>
unsigned long long TSLQueue<T>::size() { unsigned long TSLQueue<T>::size() {
std::lock_guard lock(mutex); std::lock_guard lock(mutex);
return msize; return msize;
} }
@ -277,7 +303,7 @@ bool TSLQueue<T>::TSLQNode::isNormal() const {
template <typename T> template <typename T>
TSLQueue<T>::TSLQIter::TSLQIter(std::mutex &mutex, TSLQueue<T>::TSLQIter::TSLQIter(std::mutex &mutex,
std::weak_ptr<TSLQNode> currentNode, std::weak_ptr<TSLQNode> currentNode,
unsigned long long *msize) : unsigned long *msize) :
lock(mutex), lock(mutex),
currentNode(currentNode), currentNode(currentNode),
msize(msize) msize(msize)

View file

@ -33,6 +33,7 @@
#include <iostream> #include <iostream>
#include "TSQueue.hpp" #include "TSQueue.hpp"
#include "TSLQueue.hpp"
#include "UDPConnection.h" #include "UDPConnection.h"
#include <sodium.h> #include <sodium.h>
@ -153,6 +154,9 @@ private:
case UDPC_LoggingType::UDPC_INFO: case UDPC_LoggingType::UDPC_INFO:
std::cerr << "INFO: "; std::cerr << "INFO: ";
break; break;
case UDPC_LoggingType::UDPC_DEBUG:
std::cerr << "DEBUG: ";
break;
default: default:
return; return;
} }
@ -197,8 +201,8 @@ public:
std::unordered_map<struct in6_addr, std::unordered_set<UDPC_ConnectionId, ConnectionIdHasher>, IPV6_Hasher> addrConMap; std::unordered_map<struct in6_addr, std::unordered_set<UDPC_ConnectionId, ConnectionIdHasher>, IPV6_Hasher> addrConMap;
// id to ipv6 address and port (as UDPC_ConnectionId) // id to ipv6 address and port (as UDPC_ConnectionId)
std::unordered_map<uint32_t, UDPC_ConnectionId> idMap; std::unordered_map<uint32_t, UDPC_ConnectionId> idMap;
TSQueue<UDPC_PacketInfo> receivedPkts; TSLQueue<UDPC_PacketInfo> receivedPkts;
TSQueue<UDPC_PacketInfo> cSendPkts; TSLQueue<UDPC_PacketInfo> cSendPkts;
std::default_random_engine rng_engine; std::default_random_engine rng_engine;

View file

@ -165,13 +165,13 @@ flags(),
isAcceptNewConnections(true), isAcceptNewConnections(true),
protocolID(UDPC_DEFAULT_PROTOCOL_ID), protocolID(UDPC_DEFAULT_PROTOCOL_ID),
#ifndef NDEBUG #ifndef NDEBUG
loggingType(UDPC_INFO), loggingType(UDPC_DEBUG),
#else #else
loggingType(UDPC_WARNING), loggingType(UDPC_WARNING),
#endif #endif
atostrBufIndex(0), atostrBufIndex(0),
receivedPkts(UDPC_RECEIVED_PKTS_MAX_SIZE), receivedPkts(),
cSendPkts(UDPC_QUEUED_PKTS_MAX_SIZE), cSendPkts(),
rng_engine(), rng_engine(),
mutex() mutex()
{ {
@ -199,12 +199,21 @@ bool UDPC::Context::willLog(UDPC_LoggingType type) {
case UDPC_LoggingType::UDPC_WARNING: case UDPC_LoggingType::UDPC_WARNING:
return type == UDPC_LoggingType::UDPC_ERROR return type == UDPC_LoggingType::UDPC_ERROR
|| type == UDPC_LoggingType::UDPC_WARNING; || type == UDPC_LoggingType::UDPC_WARNING;
case UDPC_LoggingType::UDPC_INFO:
return type == UDPC_LoggingType::UDPC_ERROR
|| type == UDPC_LoggingType::UDPC_WARNING
|| type == UDPC_LoggingType::UDPC_INFO;
case UDPC_LoggingType::UDPC_VERBOSE: case UDPC_LoggingType::UDPC_VERBOSE:
return type == UDPC_LoggingType::UDPC_ERROR return type == UDPC_LoggingType::UDPC_ERROR
|| type == UDPC_LoggingType::UDPC_WARNING || type == UDPC_LoggingType::UDPC_WARNING
|| type == UDPC_LoggingType::UDPC_INFO
|| type == UDPC_LoggingType::UDPC_VERBOSE; || type == UDPC_LoggingType::UDPC_VERBOSE;
case UDPC_LoggingType::UDPC_INFO: case UDPC_LoggingType::UDPC_DEBUG:
return type != UDPC_LoggingType::UDPC_SILENT; 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;
default: default:
return false; return false;
} }
@ -238,7 +247,7 @@ void UDPC::Context::update_impl() {
if(iter->second.flags.test(1) && !iter->second.flags.test(2)) { if(iter->second.flags.test(1) && !iter->second.flags.test(2)) {
// good mode, bad rtt // good mode, bad rtt
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_INFO, UDPC_LoggingType::UDPC_VERBOSE,
"Switching to bad mode in connection with ", "Switching to bad mode in connection with ",
UDPC_atostr((UDPC_HContext)this, iter->first.addr), UDPC_atostr((UDPC_HContext)this, iter->first.addr),
", port = ", ", port = ",
@ -264,7 +273,7 @@ void UDPC::Context::update_impl() {
iter->second.toggleTimer = std::chrono::steady_clock::duration::zero(); iter->second.toggleTimer = std::chrono::steady_clock::duration::zero();
iter->second.toggledTimer = std::chrono::steady_clock::duration::zero(); iter->second.toggledTimer = std::chrono::steady_clock::duration::zero();
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_INFO, UDPC_LoggingType::UDPC_VERBOSE,
"Switching to good mode in connection with ", "Switching to good mode in connection with ",
UDPC_atostr((UDPC_HContext)this, iter->first.addr), UDPC_atostr((UDPC_HContext)this, iter->first.addr),
", port = ", ", port = ",
@ -315,13 +324,33 @@ void UDPC::Context::update_impl() {
// move queued in cSendPkts to existing connection's sendPkts // move queued in cSendPkts to existing connection's sendPkts
{ {
unsigned int rsize = 0; auto sendIter = cSendPkts.begin();
do { while(true) {
auto next = cSendPkts.top_and_pop_and_rsize(&rsize); auto next = sendIter.current();
if(next) { if(next) {
if(auto iter = conMap.find(next.value().receiver); if(auto iter = conMap.find(next.value().receiver);
iter != conMap.end()) { iter != conMap.end()) {
if(iter->second.sendPkts.size() >= UDPC_QUEUED_PKTS_MAX_SIZE) {
UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_DEBUG,
"Not queueing packet to ",
UDPC_atostr((UDPC_HContext)this,
next.value().receiver.addr),
", port = ",
next.value().receiver.port,
", connection's queue reached max size");
if(sendIter.next()) {
continue;
} else {
break;
}
}
iter->second.sendPkts.push_back(next.value()); iter->second.sendPkts.push_back(next.value());
if(sendIter.remove()) {
continue;
} else {
break;
}
} else { } else {
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_WARNING, UDPC_LoggingType::UDPC_WARNING,
@ -332,9 +361,16 @@ void UDPC::Context::update_impl() {
", port = ", ", port = ",
next.value().receiver.port, next.value().receiver.port,
" due to connection not existing"); " due to connection not existing");
if(sendIter.remove()) {
continue;
} else {
break;
}
}
} else {
break;
} }
} }
} while(rsize != 0);
} }
// update send (only if triggerSend flag is set) // update send (only if triggerSend flag is set)
@ -618,7 +654,7 @@ void UDPC::Context::update_impl() {
else if(bytes < UDPC_MIN_HEADER_SIZE) { else if(bytes < UDPC_MIN_HEADER_SIZE) {
// packet size is too small, invalid packet // packet size is too small, invalid packet
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_INFO, UDPC_LoggingType::UDPC_VERBOSE,
"Received packet is smaller than header, ignoring packet from ", "Received packet is smaller than header, ignoring packet from ",
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr), UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
", port = ", ", port = ",
@ -630,7 +666,7 @@ void UDPC::Context::update_impl() {
if(temp != protocolID) { if(temp != protocolID) {
// Invalid protocol id in packet // Invalid protocol id in packet
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_INFO, UDPC_LoggingType::UDPC_VERBOSE,
"Received packet has invalid protocol id, ignoring packet from ", "Received packet has invalid protocol id, ignoring packet from ",
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr), UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
", port = ", ", port = ",
@ -652,7 +688,7 @@ void UDPC::Context::update_impl() {
if(isConnect && bytes != UDPC_CON_HEADER_SIZE) { if(isConnect && bytes != UDPC_CON_HEADER_SIZE) {
// invalid packet size // invalid packet size
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_INFO, UDPC_LoggingType::UDPC_VERBOSE,
"Got connect packet of invalid size from ", "Got connect packet of invalid size from ",
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr), UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
", port = ", ", port = ",
@ -662,7 +698,7 @@ void UDPC::Context::update_impl() {
} else if (!isConnect && bytes < (int)UDPC_FULL_HEADER_SIZE) { } else if (!isConnect && bytes < (int)UDPC_FULL_HEADER_SIZE) {
// packet is too small // packet is too small
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_INFO, UDPC_LoggingType::UDPC_VERBOSE,
"Got non-connect packet of invalid size from ", "Got non-connect packet of invalid size from ",
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr), UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
", port = ", ", port = ",
@ -692,7 +728,7 @@ void UDPC::Context::update_impl() {
std::memcpy(newConnection.peer_pk, recvBuf + UDPC_MIN_HEADER_SIZE, std::memcpy(newConnection.peer_pk, recvBuf + UDPC_MIN_HEADER_SIZE,
crypto_sign_PUBLICKEYBYTES); crypto_sign_PUBLICKEYBYTES);
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_VERBOSE, 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 = ",
@ -726,7 +762,7 @@ void UDPC::Context::update_impl() {
std::memcpy(iter->second.peer_pk, recvBuf + UDPC_MIN_HEADER_SIZE, std::memcpy(iter->second.peer_pk, recvBuf + UDPC_MIN_HEADER_SIZE,
crypto_sign_PUBLICKEYBYTES); crypto_sign_PUBLICKEYBYTES);
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_VERBOSE, 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 = ",
@ -753,7 +789,7 @@ void UDPC::Context::update_impl() {
iter->second.peer_pk) != 0) { iter->second.peer_pk) != 0) {
UDPC_CHECK_LOG( UDPC_CHECK_LOG(
this, this,
UDPC_LoggingType::UDPC_VERBOSE, UDPC_LoggingType::UDPC_INFO,
"Failed to verify received packet from", "Failed to verify received packet from",
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr), UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
", port = ", ", port = ",
@ -764,7 +800,7 @@ void UDPC::Context::update_impl() {
// packet is valid // packet is valid
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_INFO, UDPC_LoggingType::UDPC_VERBOSE,
"Received valid packet from ", "Received valid packet from ",
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr), UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
", port = ", ", port = ",
@ -790,7 +826,7 @@ void UDPC::Context::update_impl() {
iter->second.flags.set(2, iter->second.rtt <= UDPC::GOOD_RTT_LIMIT); iter->second.flags.set(2, iter->second.rtt <= UDPC::GOOD_RTT_LIMIT);
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_INFO, UDPC_LoggingType::UDPC_VERBOSE,
"RTT: ", "RTT: ",
UDPC::durationToFSec(iter->second.rtt) * 1000.0f, UDPC::durationToFSec(iter->second.rtt) * 1000.0f,
" milliseconds"); " milliseconds");
@ -823,7 +859,7 @@ void UDPC::Context::update_impl() {
if(duration > UDPC::PACKET_TIMEOUT_TIME) { if(duration > UDPC::PACKET_TIMEOUT_TIME) {
if(sentIter->dataSize <= UDPC_FULL_HEADER_SIZE) { if(sentIter->dataSize <= UDPC_FULL_HEADER_SIZE) {
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_INFO, UDPC_LoggingType::UDPC_VERBOSE,
"Timed out packet has no payload (probably " "Timed out packet has no payload (probably "
"heartbeat packet), ignoring it"); "heartbeat packet), ignoring it");
sentIter->flags |= 0x8; sentIter->flags |= 0x8;
@ -858,7 +894,7 @@ void UDPC::Context::update_impl() {
if((iter->second.ack & (0x80000000 >> (diff - 1))) != 0) { if((iter->second.ack & (0x80000000 >> (diff - 1))) != 0) {
// already received packet // already received packet
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_INFO, UDPC_LoggingType::UDPC_VERBOSE,
"Received packet is already marked as received, ignoring it"); "Received packet is already marked as received, ignoring it");
return; return;
} }
@ -872,7 +908,7 @@ void UDPC::Context::update_impl() {
if((iter->second.ack & (0x80000000 >> (diff - 1))) != 0) { if((iter->second.ack & (0x80000000 >> (diff - 1))) != 0) {
// already received packet // already received packet
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_INFO, UDPC_LoggingType::UDPC_VERBOSE,
"Received packet is already marked as received, ignoring it"); "Received packet is already marked as received, ignoring it");
return; return;
} }
@ -887,14 +923,14 @@ void UDPC::Context::update_impl() {
} else { } else {
// already received packet // already received packet
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_INFO, UDPC_LoggingType::UDPC_VERBOSE,
"Received packet is already marked as received, ignoring it"); "Received packet is already marked as received, ignoring it");
return; return;
} }
if(isOutOfOrder) { if(isOutOfOrder) {
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_VERBOSE, UDPC_LoggingType::UDPC_INFO,
"Received packet is out of order"); "Received packet is out of order");
} }
@ -912,13 +948,7 @@ void UDPC::Context::update_impl() {
recPktInfo.sender.port = ntohs(receivedData.sin6_port); recPktInfo.sender.port = ntohs(receivedData.sin6_port);
recPktInfo.receiver.port = ntohs(socketInfo.sin6_port); recPktInfo.receiver.port = ntohs(socketInfo.sin6_port);
if(!receivedPkts.push(recPktInfo)) {
UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_WARNING,
"receivedPkts is full, removing oldest entry to make room");
receivedPkts.pop();
receivedPkts.push(recPktInfo); receivedPkts.push(recPktInfo);
}
} else if(bytes == UDPC_FULL_HEADER_SIZE) { } else if(bytes == UDPC_FULL_HEADER_SIZE) {
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_VERBOSE, UDPC_LoggingType::UDPC_VERBOSE,
@ -1228,21 +1258,12 @@ void UDPC_client_initiate_connection(UDPC_HContext ctx, UDPC_ConnectionId connec
addrConIter = insertResult.first; addrConIter = insertResult.first;
} }
addrConIter->second.insert(connectionId); addrConIter->second.insert(connectionId);
UDPC_CHECK_LOG(c, UDPC_LoggingType::UDPC_VERBOSE, "client_initiate_connection: Initiating connection..."); UDPC_CHECK_LOG(c, UDPC_LoggingType::UDPC_INFO, "client_initiate_connection: Initiating connection...");
} else { } else {
UDPC_CHECK_LOG(c, UDPC_LoggingType::UDPC_ERROR, "client_initiate_connection: Already connected to peer"); UDPC_CHECK_LOG(c, UDPC_LoggingType::UDPC_ERROR, "client_initiate_connection: Already connected to peer");
} }
} }
int UDPC_get_queue_send_available(UDPC_HContext ctx) {
UDPC::Context *c = UDPC::verifyContext(ctx);
if(!c) {
return 0;
}
return c->cSendPkts.remaining_capacity();
}
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) {
if(size == 0 || !data) { if(size == 0 || !data) {
@ -1252,15 +1273,6 @@ void UDPC_queue_send(UDPC_HContext ctx, UDPC_ConnectionId destinationId,
UDPC::Context *c = UDPC::verifyContext(ctx); UDPC::Context *c = UDPC::verifyContext(ctx);
if(!c) { if(!c) {
return; return;
} else if(c->cSendPkts.full()) {
UDPC_CHECK_LOG(c,
UDPC_LoggingType::UDPC_ERROR,
"Failed to queue packet to ",
UDPC_atostr(ctx, destinationId.addr),
", port = ",
destinationId.port,
" because queue is full");
return;
} }
UDPC_PacketInfo sendInfo = UDPC::get_empty_pinfo(); UDPC_PacketInfo sendInfo = UDPC::get_empty_pinfo();
@ -1275,6 +1287,15 @@ void UDPC_queue_send(UDPC_HContext ctx, UDPC_ConnectionId destinationId,
c->cSendPkts.push(sendInfo); c->cSendPkts.push(sendInfo);
} }
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();
}
int UDPC_set_accept_new_connections(UDPC_HContext ctx, int isAccepting) { int UDPC_set_accept_new_connections(UDPC_HContext ctx, int isAccepting) {
UDPC::Context *c = UDPC::verifyContext(ctx); UDPC::Context *c = UDPC::verifyContext(ctx);
if(!c) { if(!c) {
@ -1386,7 +1407,7 @@ UDPC_LoggingType UDPC_set_logging_type(UDPC_HContext ctx, UDPC_LoggingType loggi
return static_cast<UDPC_LoggingType>(c->loggingType.exchange(loggingType)); return static_cast<UDPC_LoggingType>(c->loggingType.exchange(loggingType));
} }
UDPC_PacketInfo UDPC_get_received(UDPC_HContext ctx, unsigned int *remaining) { UDPC_PacketInfo UDPC_get_received(UDPC_HContext ctx, unsigned long *remaining) {
UDPC::Context *c = UDPC::verifyContext(ctx); UDPC::Context *c = UDPC::verifyContext(ctx);
if(!c) { if(!c) {
return UDPC::get_empty_pinfo(); return UDPC::get_empty_pinfo();
@ -1399,25 +1420,6 @@ UDPC_PacketInfo UDPC_get_received(UDPC_HContext ctx, unsigned int *remaining) {
return UDPC::get_empty_pinfo(); return UDPC::get_empty_pinfo();
} }
int UDPC_set_received_capacity(UDPC_HContext ctx, unsigned int newCapacity) {
if(newCapacity == 0) {
return 0;
}
UDPC::Context *c = UDPC::verifyContext(ctx);
if(!c) {
return 0;
}
unsigned int status = 0;
c->receivedPkts.changeCapacity(newCapacity, &status);
if(status == 1) {
UDPC_CHECK_LOG(c, UDPC_LoggingType::UDPC_WARNING,
"Received Queue: Previous size was truncated to new capacity");
}
return 1;
}
const char *UDPC_atostr_cid(UDPC_HContext ctx, UDPC_ConnectionId connectionId) { const char *UDPC_atostr_cid(UDPC_HContext ctx, UDPC_ConnectionId connectionId) {
return UDPC_atostr(ctx, connectionId.addr); return UDPC_atostr(ctx, connectionId.addr);
} }

View file

@ -65,7 +65,7 @@ extern "C" {
struct UDPC_Context; struct UDPC_Context;
typedef struct UDPC_Context *UDPC_HContext; typedef struct UDPC_Context *UDPC_HContext;
typedef enum { UDPC_SILENT, UDPC_ERROR, UDPC_WARNING, UDPC_VERBOSE, UDPC_INFO } UDPC_LoggingType; typedef enum { UDPC_SILENT, UDPC_ERROR, UDPC_WARNING, UDPC_INFO, UDPC_VERBOSE, UDPC_DEBUG } UDPC_LoggingType;
typedef struct { typedef struct {
UDPC_IPV6_ADDR_TYPE addr; UDPC_IPV6_ADDR_TYPE addr;
@ -105,11 +105,11 @@ 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 UDPC_get_queue_send_available(UDPC_HContext ctx);
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);
unsigned long UDPC_get_queue_send_current_size(UDPC_HContext ctx);
int UDPC_set_accept_new_connections(UDPC_HContext ctx, int isAccepting); int UDPC_set_accept_new_connections(UDPC_HContext ctx, int isAccepting);
int UDPC_drop_connection(UDPC_HContext ctx, UDPC_ConnectionId connectionId, bool dropAllWithAddr); int UDPC_drop_connection(UDPC_HContext ctx, UDPC_ConnectionId connectionId, bool dropAllWithAddr);
@ -124,9 +124,7 @@ uint32_t UDPC_set_protocol_id(UDPC_HContext ctx, uint32_t id);
UDPC_LoggingType UDPC_set_logging_type(UDPC_HContext ctx, UDPC_LoggingType loggingType); UDPC_LoggingType UDPC_set_logging_type(UDPC_HContext ctx, UDPC_LoggingType loggingType);
UDPC_PacketInfo UDPC_get_received(UDPC_HContext ctx, unsigned int *remaining); UDPC_PacketInfo UDPC_get_received(UDPC_HContext ctx, unsigned long *remaining);
int UDPC_set_received_capacity(UDPC_HContext ctx, unsigned int newCapacity);
const char *UDPC_atostr_cid(UDPC_HContext ctx, UDPC_ConnectionId connectionId); const char *UDPC_atostr_cid(UDPC_HContext ctx, UDPC_ConnectionId connectionId);

View file

@ -8,6 +8,8 @@
#include <UDPConnection.h> #include <UDPConnection.h>
#define QUEUED_MAX_SIZE 32
static const std::regex ipv6_regex_linkonly = std::regex(R"d(fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,})d"); static const std::regex ipv6_regex_linkonly = std::regex(R"d(fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,})d");
void usage() { void usage() {
@ -18,6 +20,7 @@ void usage() {
puts("-cp <port> - connection port (client only)"); puts("-cp <port> - connection port (client only)");
puts("-t <tick_count>"); puts("-t <tick_count>");
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");
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
@ -34,6 +37,7 @@ int main(int argc, char **argv) {
const char *connectionPort = nullptr; const char *connectionPort = nullptr;
unsigned int tickLimit = 15; unsigned int tickLimit = 15;
bool noPayload = false; bool noPayload = false;
UDPC_LoggingType logLevel = UDPC_LoggingType::UDPC_DEBUG;
while(argc > 0) { while(argc > 0) {
if(std::strcmp(argv[0], "-c") == 0) { if(std::strcmp(argv[0], "-c") == 0) {
isClient = true; isClient = true;
@ -58,6 +62,26 @@ int main(int argc, char **argv) {
} else if(std::strcmp(argv[0], "-n") == 0) { } else if(std::strcmp(argv[0], "-n") == 0) {
noPayload = true; noPayload = true;
puts("Disabling sending payload"); puts("Disabling sending payload");
} else if(std::strcmp(argv[0], "-l") == 0) {
--argc; ++argv;
if(std::strcmp(argv[0], "silent") == 0) {
logLevel = UDPC_LoggingType::UDPC_SILENT;
} else if(std::strcmp(argv[0], "error") == 0) {
logLevel = UDPC_LoggingType::UDPC_ERROR;
} else if(std::strcmp(argv[0], "warning") == 0) {
logLevel = UDPC_LoggingType::UDPC_WARNING;
} else if(std::strcmp(argv[0], "info") == 0) {
logLevel = UDPC_LoggingType::UDPC_INFO;
} else if(std::strcmp(argv[0], "verbose") == 0) {
logLevel = UDPC_LoggingType::UDPC_VERBOSE;
} else if(std::strcmp(argv[0], "debug") == 0) {
logLevel = UDPC_LoggingType::UDPC_DEBUG;
} else {
printf("ERROR: invalid argument \"%s\", expected "
"silent|error|warning|info|verbose|debug", argv[0]);
usage();
return 1;
}
} else { } else {
printf("ERROR: invalid argument \"%s\"\n", argv[0]); printf("ERROR: invalid argument \"%s\"\n", argv[0]);
usage(); usage();
@ -106,10 +130,11 @@ int main(int argc, char **argv) {
puts("ERROR: context is NULL"); puts("ERROR: context is NULL");
return 1; return 1;
} }
UDPC_set_logging_type(context, UDPC_LoggingType::UDPC_INFO); UDPC_set_logging_type(context, logLevel);
unsigned int tick = 0; unsigned int tick = 0;
unsigned int temp = 0; unsigned int temp = 0;
unsigned int temp2, temp3; unsigned int temp2, temp3;
unsigned long size;
UDPC_ConnectionId *list = nullptr; UDPC_ConnectionId *list = nullptr;
std::vector<unsigned int> sendIds; std::vector<unsigned int> sendIds;
UDPC_PacketInfo received; UDPC_PacketInfo received;
@ -126,7 +151,8 @@ int main(int argc, char **argv) {
} else if(sendIds.size() > temp) { } else if(sendIds.size() > temp) {
sendIds.resize(temp); sendIds.resize(temp);
} }
temp2 = UDPC_get_queue_send_available(context); size = UDPC_get_queue_send_current_size(context);
temp2 = size < QUEUED_MAX_SIZE ? QUEUED_MAX_SIZE - size : 0;
for(unsigned int i = 0; i < temp2; ++i) { for(unsigned int i = 0; i < temp2; ++i) {
temp3 = htonl(sendIds[i % temp]++); temp3 = htonl(sendIds[i % temp]++);
UDPC_queue_send(context, list[i % temp], 0, &temp3, sizeof(unsigned int)); UDPC_queue_send(context, list[i % temp], 0, &temp3, sizeof(unsigned int));
@ -134,14 +160,14 @@ int main(int argc, char **argv) {
UDPC_free_list_connected(list); UDPC_free_list_connected(list);
} }
do { do {
received = UDPC_get_received(context, &temp); received = UDPC_get_received(context, &size);
if(received.dataSize == sizeof(unsigned int)) { if(received.dataSize == sizeof(unsigned int)) {
if((received.flags & 0x8) != 0) { if((received.flags & 0x8) != 0) {
temp2 = ntohl(*((unsigned int*)received.data)); temp2 = ntohl(*((unsigned int*)received.data));
printf("Got out of order, data = %u\n", temp2); printf("Got out of order, data = %u\n", temp2);
} }
} }
} while (temp > 0); } while (size > 0);
} }
if(tick++ > tickLimit) { if(tick++ > tickLimit) {
break; break;