Rework sendPkts (sending queue)

Changed sendPkts in ConnectionData to std::deque, added a TSQueue
cSendPkts to Context. Queued packets will be moved to corresponding
ConnectionData instances during update, dropping with a warning those
where a connection does not exist.

Minor other fixes.

Some additions to TSQueue.
This commit is contained in:
Stephen Seo 2019-09-27 20:19:48 +09:00
parent 98e88237ce
commit b11d87ca12
5 changed files with 69 additions and 40 deletions

View file

@ -37,7 +37,9 @@ class TSQueue {
void changeCapacity(unsigned int newCapacity, unsigned int *status); void changeCapacity(unsigned int newCapacity, unsigned int *status);
unsigned int size(); unsigned int size();
unsigned int capacity(); unsigned int capacity();
unsigned int remaining_capacity();
bool empty(); bool empty();
bool full();
private: private:
std::mutex mutex; std::mutex mutex;
@ -165,6 +167,13 @@ unsigned int TSQueue<T>::capacity() {
return capacity; return capacity;
} }
template <typename T>
unsigned int TSQueue<T>::remaining_capacity() {
std::lock_guard<std::mutex> lock(mutex);
unsigned int remaining = rb.getCapacity() - rb.getSize();
return remaining;
}
template <typename T> template <typename T>
bool TSQueue<T>::empty() { bool TSQueue<T>::empty() {
// No lock required, since this is calling size() that uses a lock // No lock required, since this is calling size() that uses a lock
@ -172,4 +181,11 @@ bool TSQueue<T>::empty() {
return size == 0; return size == 0;
} }
template <typename T>
bool TSQueue<T>::full() {
// No lock required, calling remaining_capacity() that uses a lock
unsigned int remaining = remaining_capacity();
return remaining == 0;
}
#endif #endif

View file

@ -4,7 +4,7 @@
#define UDPC_CONTEXT_IDENTIFIER 0x902F4DB3 #define UDPC_CONTEXT_IDENTIFIER 0x902F4DB3
#define UDPC_SENT_PKTS_MAX_SIZE 33 #define UDPC_SENT_PKTS_MAX_SIZE 33
#define UDPC_QUEUED_PKTS_MAX_SIZE 32 #define UDPC_QUEUED_PKTS_MAX_SIZE 64
#define UDPC_RECEIVED_PKTS_MAX_SIZE 64 #define UDPC_RECEIVED_PKTS_MAX_SIZE 64
#define UDPC_ID_CONNECT 0x80000000 #define UDPC_ID_CONNECT 0x80000000
@ -110,8 +110,8 @@ struct ConnectionData {
uint32_t scope_id; uint32_t scope_id;
uint16_t port; // in native order uint16_t port; // in native order
std::deque<UDPC_PacketInfo> sentPkts; std::deque<UDPC_PacketInfo> sentPkts;
TSQueue<UDPC_PacketInfo> sendPkts; std::deque<UDPC_PacketInfo> sendPkts;
TSQueue<UDPC_PacketInfo> priorityPkts; std::deque<UDPC_PacketInfo> priorityPkts;
// pkt id to pkt shared_ptr // pkt id to pkt shared_ptr
std::unordered_map<uint32_t, SentPktInfo::Ptr> sentInfoMap; std::unordered_map<uint32_t, SentPktInfo::Ptr> sentInfoMap;
std::chrono::steady_clock::time_point received; std::chrono::steady_clock::time_point received;
@ -266,6 +266,7 @@ public:
// 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; TSQueue<UDPC_PacketInfo> receivedPkts;
TSQueue<UDPC_PacketInfo> cSendPkts;
std::default_random_engine rng_engine; std::default_random_engine rng_engine;

View file

@ -89,8 +89,8 @@ toggledTimer(std::chrono::steady_clock::duration::zero()),
addr({0}), addr({0}),
port(0), port(0),
sentPkts(), sentPkts(),
sendPkts(UDPC_QUEUED_PKTS_MAX_SIZE), sendPkts(),
priorityPkts(UDPC_QUEUED_PKTS_MAX_SIZE), priorityPkts(),
received(std::chrono::steady_clock::now()), received(std::chrono::steady_clock::now()),
sent(std::chrono::steady_clock::now()), sent(std::chrono::steady_clock::now()),
rtt(std::chrono::steady_clock::duration::zero()) rtt(std::chrono::steady_clock::duration::zero())
@ -125,8 +125,8 @@ addr(addr),
scope_id(scope_id), scope_id(scope_id),
port(port), port(port),
sentPkts(), sentPkts(),
sendPkts(UDPC_QUEUED_PKTS_MAX_SIZE), sendPkts(),
priorityPkts(UDPC_QUEUED_PKTS_MAX_SIZE), priorityPkts(),
received(std::chrono::steady_clock::now()), received(std::chrono::steady_clock::now()),
sent(std::chrono::steady_clock::now()), sent(std::chrono::steady_clock::now()),
rtt(std::chrono::steady_clock::duration::zero()) rtt(std::chrono::steady_clock::duration::zero())
@ -171,6 +171,7 @@ loggingType(UDPC_WARNING),
#endif #endif
atostrBufIndex(0), atostrBufIndex(0),
receivedPkts(UDPC_RECEIVED_PKTS_MAX_SIZE), receivedPkts(UDPC_RECEIVED_PKTS_MAX_SIZE),
cSendPkts(UDPC_QUEUED_PKTS_MAX_SIZE),
rng_engine(), rng_engine(),
mutex() mutex()
{ {
@ -312,6 +313,30 @@ void UDPC::Context::update_impl() {
} }
} }
// move queued in cSendPkts to existing connection's sendPkts
{
unsigned int rsize = 0;
do {
auto next = cSendPkts.top_and_pop_and_rsize(&rsize);
if(next) {
if(auto iter = conMap.find(next.value().receiver);
iter != conMap.end()) {
iter->second.sendPkts.push_back(next.value());
} else {
UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_WARNING,
"Dropped queued packet to ",
UDPC_atostr(
(UDPC_HContext)this,
next.value().receiver.addr),
", port = ",
next.value().receiver.port,
" due to connection not existing");
}
}
} while(rsize != 0);
}
// update send (only if triggerSend flag is set) // update send (only if triggerSend flag is set)
for(auto iter = conMap.begin(); iter != conMap.end(); ++iter) { for(auto iter = conMap.begin(); iter != conMap.end(); ++iter) {
if(!iter->second.flags.test(0)) { if(!iter->second.flags.test(0)) {
@ -479,13 +504,12 @@ void UDPC::Context::update_impl() {
UDPC_PacketInfo pInfo = UDPC::get_empty_pinfo(); UDPC_PacketInfo pInfo = UDPC::get_empty_pinfo();
bool isResending = false; bool isResending = false;
if(!iter->second.priorityPkts.empty()) { if(!iter->second.priorityPkts.empty()) {
// TODO verify getting struct copy is valid pInfo = iter->second.priorityPkts.front();
pInfo = std::move(iter->second.priorityPkts.top().value()); iter->second.priorityPkts.pop_front();
iter->second.priorityPkts.pop();
isResending = true; isResending = true;
} else { } else {
pInfo = std::move(iter->second.sendPkts.top().value()); pInfo = iter->second.sendPkts.front();
iter->second.sendPkts.pop(); 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 = std::make_unique<char[]>(UDPC_FULL_HEADER_SIZE + pInfo.dataSize);
UDPC::preparePacket( UDPC::preparePacket(
@ -810,7 +834,7 @@ void UDPC::Context::update_impl() {
resendingData.dataSize = sentIter->dataSize - UDPC_FULL_HEADER_SIZE; resendingData.dataSize = sentIter->dataSize - UDPC_FULL_HEADER_SIZE;
std::memcpy(resendingData.data, sentIter->data + UDPC_FULL_HEADER_SIZE, resendingData.dataSize); std::memcpy(resendingData.data, sentIter->data + UDPC_FULL_HEADER_SIZE, resendingData.dataSize);
resendingData.flags = 0; resendingData.flags = 0;
iter->second.priorityPkts.push(resendingData); iter->second.priorityPkts.push_back(resendingData);
} }
break; break;
} }
@ -1210,20 +1234,13 @@ void UDPC_client_initiate_connection(UDPC_HContext ctx, UDPC_ConnectionId connec
} }
} }
int UDPC_get_queue_send_available(UDPC_HContext ctx, UDPC_ConnectionId connectionId) { int UDPC_get_queue_send_available(UDPC_HContext ctx) {
UDPC::Context *c = UDPC::verifyContext(ctx); UDPC::Context *c = UDPC::verifyContext(ctx);
if(!c) { if(!c) {
return 0; return 0;
} }
std::lock_guard<std::mutex> lock(c->mutex); return c->cSendPkts.remaining_capacity();
auto iter = c->conMap.find(connectionId);
if(iter != c->conMap.end()) {
return iter->second.sendPkts.capacity() - iter->second.sendPkts.size();
} else {
return 0;
}
} }
void UDPC_queue_send(UDPC_HContext ctx, UDPC_ConnectionId destinationId, void UDPC_queue_send(UDPC_HContext ctx, UDPC_ConnectionId destinationId,
@ -1235,16 +1252,14 @@ 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()) {
std::lock_guard<std::mutex> lock(c->mutex);
auto iter = c->conMap.find(destinationId);
if(iter == c->conMap.end()) {
UDPC_CHECK_LOG(c, UDPC_CHECK_LOG(c,
UDPC_LoggingType::UDPC_ERROR, UDPC_LoggingType::UDPC_ERROR,
"Failed to add packet to queue, no established connection " "Failed to queue packet to ",
"with recipient"); UDPC_atostr(ctx, destinationId.addr),
", port = ",
destinationId.port,
" because queue is full");
return; return;
} }
@ -1254,10 +1269,10 @@ void UDPC_queue_send(UDPC_HContext ctx, UDPC_ConnectionId destinationId,
sendInfo.sender.addr = in6addr_loopback; sendInfo.sender.addr = in6addr_loopback;
sendInfo.sender.port = ntohs(c->socketInfo.sin6_port); sendInfo.sender.port = ntohs(c->socketInfo.sin6_port);
sendInfo.receiver.addr = destinationId.addr; sendInfo.receiver.addr = destinationId.addr;
sendInfo.receiver.port = iter->second.port; sendInfo.receiver.port = destinationId.port;
sendInfo.flags = (isChecked != 0 ? 0x0 : 0x4); sendInfo.flags = (isChecked != 0 ? 0x0 : 0x4);
iter->second.sendPkts.push(sendInfo); c->cSendPkts.push(sendInfo);
} }
int UDPC_set_accept_new_connections(UDPC_HContext ctx, int isAccepting) { int UDPC_set_accept_new_connections(UDPC_HContext ctx, int isAccepting) {
@ -1265,7 +1280,6 @@ int UDPC_set_accept_new_connections(UDPC_HContext ctx, int isAccepting) {
if(!c) { if(!c) {
return 0; return 0;
} }
std::lock_guard<std::mutex> lock(c->mutex);
return c->isAcceptNewConnections.exchange(isAccepting == 0 ? false : true); return c->isAcceptNewConnections.exchange(isAccepting == 0 ? false : true);
} }

View file

@ -105,7 +105,7 @@ 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, 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);

View file

@ -126,12 +126,10 @@ int main(int argc, char **argv) {
} else if(sendIds.size() > temp) { } else if(sendIds.size() > temp) {
sendIds.resize(temp); sendIds.resize(temp);
} }
for(unsigned int i = 0; i < temp; ++i) { temp2 = UDPC_get_queue_send_available(context);
temp2 = UDPC_get_queue_send_available(context, list[i]); for(unsigned int i = 0; i < temp2; ++i) {
for(unsigned int j = 0; j < temp2; ++j) { temp3 = htonl(sendIds[i % temp]++);
temp3 = htonl(sendIds[i]++); UDPC_queue_send(context, list[i % temp], 0, &temp3, sizeof(unsigned int));
UDPC_queue_send(context, list[i], 0, &temp3, sizeof(unsigned int));
}
} }
UDPC_free_list_connected(list); UDPC_free_list_connected(list);
} }