isAcceptNewConnections(true),
protocolID(UDPC_DEFAULT_PROTOCOL_ID),
#ifndef NDEBUG
-loggingType(UDPC_INFO),
+loggingType(UDPC_DEBUG),
#else
loggingType(UDPC_WARNING),
#endif
atostrBufIndex(0),
-receivedPkts(UDPC_RECEIVED_PKTS_MAX_SIZE),
-cSendPkts(UDPC_QUEUED_PKTS_MAX_SIZE),
+receivedPkts(),
+cSendPkts(),
rng_engine(),
mutex()
{
case UDPC_LoggingType::UDPC_WARNING:
return type == UDPC_LoggingType::UDPC_ERROR
|| 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:
return type == UDPC_LoggingType::UDPC_ERROR
|| type == UDPC_LoggingType::UDPC_WARNING
+ || type == UDPC_LoggingType::UDPC_INFO
|| type == UDPC_LoggingType::UDPC_VERBOSE;
- case UDPC_LoggingType::UDPC_INFO:
- return type != UDPC_LoggingType::UDPC_SILENT;
+ case UDPC_LoggingType::UDPC_DEBUG:
+ return type == UDPC_LoggingType::UDPC_ERROR
+ || type == UDPC_LoggingType::UDPC_WARNING
+ || type == UDPC_LoggingType::UDPC_INFO
+ || type == UDPC_LoggingType::UDPC_VERBOSE
+ || type == UDPC_LoggingType::UDPC_DEBUG;
default:
return false;
}
if(iter->second.flags.test(1) && !iter->second.flags.test(2)) {
// good mode, bad rtt
UDPC_CHECK_LOG(this,
- UDPC_LoggingType::UDPC_INFO,
+ UDPC_LoggingType::UDPC_VERBOSE,
"Switching to bad mode in connection with ",
UDPC_atostr((UDPC_HContext)this, iter->first.addr),
", port = ",
iter->second.toggleTimer = std::chrono::steady_clock::duration::zero();
iter->second.toggledTimer = std::chrono::steady_clock::duration::zero();
UDPC_CHECK_LOG(this,
- UDPC_LoggingType::UDPC_INFO,
+ UDPC_LoggingType::UDPC_VERBOSE,
"Switching to good mode in connection with ",
UDPC_atostr((UDPC_HContext)this, iter->first.addr),
", port = ",
// move queued in cSendPkts to existing connection's sendPkts
{
- unsigned int rsize = 0;
- do {
- auto next = cSendPkts.top_and_pop_and_rsize(&rsize);
+ auto sendIter = cSendPkts.begin();
+ while(true) {
+ auto next = sendIter.current();
if(next) {
if(auto iter = conMap.find(next.value().receiver);
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());
+ if(sendIter.remove()) {
+ continue;
+ } else {
+ break;
+ }
} else {
UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_WARNING,
", port = ",
next.value().receiver.port,
" due to connection not existing");
+ if(sendIter.remove()) {
+ continue;
+ } else {
+ break;
+ }
}
+ } else {
+ break;
}
- } while(rsize != 0);
+ }
}
// update send (only if triggerSend flag is set)
else if(bytes < UDPC_MIN_HEADER_SIZE) {
// packet size is too small, invalid packet
UDPC_CHECK_LOG(this,
- UDPC_LoggingType::UDPC_INFO,
+ UDPC_LoggingType::UDPC_VERBOSE,
"Received packet is smaller than header, ignoring packet from ",
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
", port = ",
if(temp != protocolID) {
// Invalid protocol id in packet
UDPC_CHECK_LOG(this,
- UDPC_LoggingType::UDPC_INFO,
+ UDPC_LoggingType::UDPC_VERBOSE,
"Received packet has invalid protocol id, ignoring packet from ",
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
", port = ",
if(isConnect && bytes != UDPC_CON_HEADER_SIZE) {
// invalid packet size
UDPC_CHECK_LOG(this,
- UDPC_LoggingType::UDPC_INFO,
+ UDPC_LoggingType::UDPC_VERBOSE,
"Got connect packet of invalid size from ",
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
", port = ",
} else if (!isConnect && bytes < (int)UDPC_FULL_HEADER_SIZE) {
// packet is too small
UDPC_CHECK_LOG(this,
- UDPC_LoggingType::UDPC_INFO,
+ UDPC_LoggingType::UDPC_VERBOSE,
"Got non-connect packet of invalid size from ",
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
", port = ",
std::memcpy(newConnection.peer_pk, recvBuf + UDPC_MIN_HEADER_SIZE,
crypto_sign_PUBLICKEYBYTES);
UDPC_CHECK_LOG(this,
- UDPC_LoggingType::UDPC_VERBOSE,
+ UDPC_LoggingType::UDPC_INFO,
"Establishing connection with client ",
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
", port = ",
std::memcpy(iter->second.peer_pk, recvBuf + UDPC_MIN_HEADER_SIZE,
crypto_sign_PUBLICKEYBYTES);
UDPC_CHECK_LOG(this,
- UDPC_LoggingType::UDPC_VERBOSE,
+ UDPC_LoggingType::UDPC_INFO,
"Established connection with server ",
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
", port = ",
iter->second.peer_pk) != 0) {
UDPC_CHECK_LOG(
this,
- UDPC_LoggingType::UDPC_VERBOSE,
+ UDPC_LoggingType::UDPC_INFO,
"Failed to verify received packet from",
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
", port = ",
// packet is valid
UDPC_CHECK_LOG(this,
- UDPC_LoggingType::UDPC_INFO,
+ UDPC_LoggingType::UDPC_VERBOSE,
"Received valid packet from ",
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
", port = ",
iter->second.flags.set(2, iter->second.rtt <= UDPC::GOOD_RTT_LIMIT);
UDPC_CHECK_LOG(this,
- UDPC_LoggingType::UDPC_INFO,
+ UDPC_LoggingType::UDPC_VERBOSE,
"RTT: ",
UDPC::durationToFSec(iter->second.rtt) * 1000.0f,
" milliseconds");
if(duration > UDPC::PACKET_TIMEOUT_TIME) {
if(sentIter->dataSize <= UDPC_FULL_HEADER_SIZE) {
UDPC_CHECK_LOG(this,
- UDPC_LoggingType::UDPC_INFO,
+ UDPC_LoggingType::UDPC_VERBOSE,
"Timed out packet has no payload (probably "
"heartbeat packet), ignoring it");
sentIter->flags |= 0x8;
if((iter->second.ack & (0x80000000 >> (diff - 1))) != 0) {
// already received packet
UDPC_CHECK_LOG(this,
- UDPC_LoggingType::UDPC_INFO,
+ UDPC_LoggingType::UDPC_VERBOSE,
"Received packet is already marked as received, ignoring it");
return;
}
if((iter->second.ack & (0x80000000 >> (diff - 1))) != 0) {
// already received packet
UDPC_CHECK_LOG(this,
- UDPC_LoggingType::UDPC_INFO,
+ UDPC_LoggingType::UDPC_VERBOSE,
"Received packet is already marked as received, ignoring it");
return;
}
} else {
// already received packet
UDPC_CHECK_LOG(this,
- UDPC_LoggingType::UDPC_INFO,
+ UDPC_LoggingType::UDPC_VERBOSE,
"Received packet is already marked as received, ignoring it");
return;
}
if(isOutOfOrder) {
UDPC_CHECK_LOG(this,
- UDPC_LoggingType::UDPC_VERBOSE,
+ UDPC_LoggingType::UDPC_INFO,
"Received packet is out of order");
}
recPktInfo.sender.port = ntohs(receivedData.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) {
UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_VERBOSE,
addrConIter = insertResult.first;
}
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 {
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,
int isChecked, void *data, uint32_t size) {
if(size == 0 || !data) {
UDPC::Context *c = UDPC::verifyContext(ctx);
if(!c) {
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();
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) {
UDPC::Context *c = UDPC::verifyContext(ctx);
if(!c) {
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);
if(!c) {
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) {
return UDPC_atostr(ctx, connectionId.addr);
}
#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");
void usage() {
puts("-cp <port> - connection port (client only)");
puts("-t <tick_count>");
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) {
const char *connectionPort = nullptr;
unsigned int tickLimit = 15;
bool noPayload = false;
+ UDPC_LoggingType logLevel = UDPC_LoggingType::UDPC_DEBUG;
while(argc > 0) {
if(std::strcmp(argv[0], "-c") == 0) {
isClient = true;
} else if(std::strcmp(argv[0], "-n") == 0) {
noPayload = true;
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 {
printf("ERROR: invalid argument \"%s\"\n", argv[0]);
usage();
puts("ERROR: context is NULL");
return 1;
}
- UDPC_set_logging_type(context, UDPC_LoggingType::UDPC_INFO);
+ UDPC_set_logging_type(context, logLevel);
unsigned int tick = 0;
unsigned int temp = 0;
unsigned int temp2, temp3;
+ unsigned long size;
UDPC_ConnectionId *list = nullptr;
std::vector<unsigned int> sendIds;
UDPC_PacketInfo received;
} else if(sendIds.size() > 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) {
temp3 = htonl(sendIds[i % temp]++);
UDPC_queue_send(context, list[i % temp], 0, &temp3, sizeof(unsigned int));
UDPC_free_list_connected(list);
}
do {
- received = UDPC_get_received(context, &temp);
+ received = UDPC_get_received(context, &size);
if(received.dataSize == sizeof(unsigned int)) {
if((received.flags & 0x8) != 0) {
temp2 = ntohl(*((unsigned int*)received.data));
printf("Got out of order, data = %u\n", temp2);
}
}
- } while (temp > 0);
+ } while (size > 0);
}
if(tick++ > tickLimit) {
break;