From 0da3a9202c732d5b491649e138ac8479e1a21818 Mon Sep 17 00:00:00 2001 From: Ivan Mahonin Date: Oct 24 2021 07:06:55 +0000 Subject: udpsendqueue --- diff --git a/udpsendqueue.cpp b/udpsendqueue.cpp new file mode 100644 index 0000000..6d3c455 --- /dev/null +++ b/udpsendqueue.cpp @@ -0,0 +1,120 @@ + +#include + +#include "tunnel.h" +#include "connection.h" +#include "udpsendqueue.h" + + + +UdpSendQueue::UdpSendQueue(Connection &connection): + connection(connection), + nextSendTime(connection.tunnel.time + connection.tunnel.udpSendDuration), + nextPartialSendTime(connection.tunnel.time + connection.tunnel.udpPartialSendDuration), + finalEntryAdded(), + nextIndex(), + freeFirst(entries), + busyFirst(), + busyLast(), + entries() +{ + Entry *e = entries; + Entry *end = e + sizeof(entries)/sizeof(*entries) - 1; + while(e < end) { e->next = e + 1; ++e; } +} + + +UdpSendQueue::~UdpSendQueue() + { } + + +UdpSendQueue::Entry* UdpSendQueue::allocEntry() { + Entry *e = freeFirst; + if (!e) return nullptr; + freeFirst = e->next; + e->prev = busyLast; + e->next = nullptr; + (e->prev ? e->prev->next : busyFirst) = e; + busyLast = e; + return e; +} + + +void UdpSendQueue::freeEntry(Entry *e) { + (e->prev ? e->prev->next : busyFirst) = e->next; + (e->next ? e->next->prev : busyLast ) = e->prev; + memset(e, 0, sizeof(*e)); + e->next = freeFirst; + freeFirst = e; +} + + +void UdpSendQueue::confirm(unsigned int index, const unsigned char *bits, unsigned int bitsCount) { + while(busyFirst && cycleLess(busyFirst->index, index)) + freeEntry(busyFirst); + Entry *e = busyFirst; + while(e) { + unsigned int bit = e->index - index; + if (bit > bitsCount) + break; + unsigned int byte = bit / 8; + bit %= 8; + if (bits[byte] & (1 << bit)) { + Entry *ee = e; + e = e->next; + freeEntry(ee); + } else { + e = e->next; + } + } +} + + +bool UdpSendQueue::sendUdp() { + Time time = connection.tunnel.time; + if (timeLess(time, nextSendTime)) + return false; + + Entry *e = busyFirst; + while(e) { + if (timeLequal(e->resendTime, time)) + break; + e = e->next; + } + + if (!e && !freeFirst) + return false; + + if (!e) { + int size = connection.tcpRecvQueue.busySize(); + if (size > PACKET_SIZE) size = PACKET_SIZE; + if (size < 0) size = 0; + + if (size == 0) { + if (connection.tcpSockId >= 0 || finalEntryAdded) { + nextPartialSendTime = time + connection.tunnel.udpPartialSendDuration; + return false; + } + } else { + if (size < PACKET_SIZE && timeLess(time, nextPartialSendTime)) + return false; + } + + if (( e = allocEntry() )) + return false; + e->index = nextIndex++; + e->size = size; + if (e->size) connection.tcpRecvQueue.pop(e->data, e->size); else finalEntryAdded = true; + } + + Packet packet; + packet.init(connection.id, e->index, CMD_DATA, e->size); + if (e->size) memcpy(packet.payload, e->data, e->size); + connection.tunnel.udpSend(packet); + + e->resendTime = time + connection.tunnel.udpResendDuration; + nextSendTime += connection.tunnel.udpPartialSendDuration; + nextPartialSendTime = time + connection.tunnel.udpPartialSendDuration; + return true; +} + diff --git a/udpsendqueue.h b/udpsendqueue.h new file mode 100644 index 0000000..98458d4 --- /dev/null +++ b/udpsendqueue.h @@ -0,0 +1,45 @@ +#ifndef UDPSENDQUEUE_H +#define UDPSENDQUEUE_H + + +#include "common.h" + + +class Connection; + + +class UdpSendQueue { +public: + struct Entry { + Entry *prev, *next; + Time resendTime; + unsigned int index; + unsigned short size; + unsigned char data[PACKET_SIZE]; + }; + +public: + Connection &connection; +private: + Time nextSendTime; + Time nextPartialSendTime; + bool finalEntryAdded; + unsigned int nextIndex; + + Entry *freeFirst; + Entry *busyFirst, *busyLast; + Entry entries[PACKETS_COUNT]; + + Entry* allocEntry(); + void freeEntry(Entry *e); + +public: + explicit UdpSendQueue(Connection &connection); + ~UdpSendQueue(); + + void confirm(unsigned int index, const unsigned char *bits, unsigned int bitsCount); + bool sendUdp(); +}; + + +#endif