|
|
0da3a9 |
|
|
|
0da3a9 |
#include <cstring></cstring>
|
|
|
0da3a9 |
|
|
|
0da3a9 |
#include "tunnel.h"
|
|
|
0da3a9 |
#include "connection.h"
|
|
|
0da3a9 |
#include "udpsendqueue.h"
|
|
|
0da3a9 |
|
|
|
0da3a9 |
|
|
|
0da3a9 |
|
|
|
0da3a9 |
UdpSendQueue::UdpSendQueue(Connection &connection):
|
|
|
0da3a9 |
connection(connection),
|
|
|
0da3a9 |
nextSendTime(connection.tunnel.time + connection.tunnel.udpSendDuration),
|
|
|
0da3a9 |
nextPartialSendTime(connection.tunnel.time + connection.tunnel.udpPartialSendDuration),
|
|
|
0da3a9 |
finalEntryAdded(),
|
|
|
0da3a9 |
nextIndex(),
|
|
|
0da3a9 |
freeFirst(entries),
|
|
|
0da3a9 |
busyFirst(),
|
|
|
0da3a9 |
busyLast(),
|
|
|
0da3a9 |
entries()
|
|
|
0da3a9 |
{
|
|
|
0da3a9 |
Entry *e = entries;
|
|
|
0da3a9 |
Entry *end = e + sizeof(entries)/sizeof(*entries) - 1;
|
|
|
0da3a9 |
while(e < end) { e->next = e + 1; ++e; }
|
|
|
0da3a9 |
}
|
|
|
0da3a9 |
|
|
|
0da3a9 |
|
|
|
0da3a9 |
UdpSendQueue::~UdpSendQueue()
|
|
|
0da3a9 |
{ }
|
|
|
0da3a9 |
|
|
|
0da3a9 |
|
|
|
0da3a9 |
UdpSendQueue::Entry* UdpSendQueue::allocEntry() {
|
|
|
0da3a9 |
Entry *e = freeFirst;
|
|
|
0da3a9 |
if (!e) return nullptr;
|
|
|
0da3a9 |
freeFirst = e->next;
|
|
|
c47604 |
e->prev = nullptr;
|
|
|
c47604 |
e->next = busyFirst;
|
|
|
c47604 |
(e->next ? e->next->prev : busyLast) = e;
|
|
|
0da3a9 |
busyLast = e;
|
|
|
0da3a9 |
return e;
|
|
|
0da3a9 |
}
|
|
|
0da3a9 |
|
|
|
0da3a9 |
|
|
|
c47604 |
void UdpSendQueue::moveToEnd(Entry *e) {
|
|
|
c47604 |
if (!e->next) return;
|
|
|
c47604 |
(e->prev ? e->prev->next : busyFirst) = e->next;
|
|
|
c47604 |
(e->next ? e->next->prev : busyLast ) = e->prev;
|
|
|
c47604 |
e->next = nullptr;
|
|
|
c47604 |
e->prev = busyLast;
|
|
|
c47604 |
(e->prev ? e->prev->next : busyFirst) = e;
|
|
|
c47604 |
}
|
|
|
c47604 |
|
|
|
c47604 |
|
|
|
0da3a9 |
void UdpSendQueue::freeEntry(Entry *e) {
|
|
|
0da3a9 |
(e->prev ? e->prev->next : busyFirst) = e->next;
|
|
|
0da3a9 |
(e->next ? e->next->prev : busyLast ) = e->prev;
|
|
|
0da3a9 |
memset(e, 0, sizeof(*e));
|
|
|
0da3a9 |
e->next = freeFirst;
|
|
|
0da3a9 |
freeFirst = e;
|
|
|
0da3a9 |
}
|
|
|
0da3a9 |
|
|
|
0da3a9 |
|
|
|
0da3a9 |
void UdpSendQueue::confirm(unsigned int index, const unsigned char *bits, unsigned int bitsCount) {
|
|
|
0da3a9 |
while(busyFirst && cycleLess(busyFirst->index, index))
|
|
|
0da3a9 |
freeEntry(busyFirst);
|
|
|
0da3a9 |
Entry *e = busyFirst;
|
|
|
0da3a9 |
while(e) {
|
|
|
0da3a9 |
unsigned int bit = e->index - index;
|
|
|
0da3a9 |
if (bit > bitsCount)
|
|
|
0da3a9 |
break;
|
|
|
0da3a9 |
unsigned int byte = bit / 8;
|
|
|
0da3a9 |
bit %= 8;
|
|
|
0da3a9 |
if (bits[byte] & (1 << bit)) {
|
|
|
0da3a9 |
Entry *ee = e;
|
|
|
0da3a9 |
e = e->next;
|
|
|
0da3a9 |
freeEntry(ee);
|
|
|
0da3a9 |
} else {
|
|
|
0da3a9 |
e = e->next;
|
|
|
0da3a9 |
}
|
|
|
0da3a9 |
}
|
|
|
0da3a9 |
}
|
|
|
0da3a9 |
|
|
|
0da3a9 |
|
|
|
873e9f |
bool UdpSendQueue::sendUdpSingle() {
|
|
|
0da3a9 |
Time time = connection.tunnel.time;
|
|
|
0da3a9 |
if (timeLess(time, nextSendTime))
|
|
|
0da3a9 |
return false;
|
|
|
0da3a9 |
|
|
|
0da3a9 |
Entry *e = busyFirst;
|
|
|
c47604 |
if (!timeLequal(e->resendTime, time))
|
|
|
c47604 |
e = nullptr;
|
|
|
0da3a9 |
|
|
|
0da3a9 |
if (!e && !freeFirst)
|
|
|
0da3a9 |
return false;
|
|
|
0da3a9 |
|
|
|
0da3a9 |
if (!e) {
|
|
|
0da3a9 |
int size = connection.tcpRecvQueue.busySize();
|
|
|
0da3a9 |
if (size > PACKET_SIZE) size = PACKET_SIZE;
|
|
|
0da3a9 |
if (size < 0) size = 0;
|
|
|
0da3a9 |
|
|
|
0da3a9 |
if (size == 0) {
|
|
|
0da3a9 |
if (connection.tcpSockId >= 0 || finalEntryAdded) {
|
|
|
0da3a9 |
nextPartialSendTime = time + connection.tunnel.udpPartialSendDuration;
|
|
|
0da3a9 |
return false;
|
|
|
0da3a9 |
}
|
|
|
0da3a9 |
} else {
|
|
|
0da3a9 |
if (size < PACKET_SIZE && timeLess(time, nextPartialSendTime))
|
|
|
0da3a9 |
return false;
|
|
|
0da3a9 |
}
|
|
|
0da3a9 |
|
|
|
0da3a9 |
if (( e = allocEntry() ))
|
|
|
0da3a9 |
return false;
|
|
|
0da3a9 |
e->index = nextIndex++;
|
|
|
0da3a9 |
e->size = size;
|
|
|
0da3a9 |
if (e->size) connection.tcpRecvQueue.pop(e->data, e->size); else finalEntryAdded = true;
|
|
|
0da3a9 |
}
|
|
|
0da3a9 |
|
|
|
0da3a9 |
Packet packet;
|
|
|
873e9f |
packet.init(connection.id.id, e->index, CMD_DATA, e->size);
|
|
|
0da3a9 |
if (e->size) memcpy(packet.payload, e->data, e->size);
|
|
|
c47604 |
connection.tunnel.sendUdpPacket(connection.id.address, packet);
|
|
|
0da3a9 |
|
|
|
0da3a9 |
e->resendTime = time + connection.tunnel.udpResendDuration;
|
|
|
0da3a9 |
nextSendTime += connection.tunnel.udpPartialSendDuration;
|
|
|
0da3a9 |
nextPartialSendTime = time + connection.tunnel.udpPartialSendDuration;
|
|
|
c47604 |
moveToEnd(e);
|
|
|
0da3a9 |
return true;
|
|
|
0da3a9 |
}
|
|
|
0da3a9 |
|
|
|
873e9f |
|
|
|
873e9f |
int UdpSendQueue::sendUdp() {
|
|
|
873e9f |
int sent = 0;
|
|
|
873e9f |
while(sendUdpSingle()) {
|
|
|
873e9f |
++sent;
|
|
|
873e9f |
if (sent == 100) {
|
|
|
873e9f |
if (timeLess(nextSendTime, connection.tunnel.time))
|
|
|
873e9f |
nextSendTime = connection.tunnel.time;
|
|
|
873e9f |
break;
|
|
|
873e9f |
}
|
|
|
873e9f |
}
|
|
|
873e9f |
return sent;
|
|
|
873e9f |
}
|
|
|
873e9f |
|
|
|
c47604 |
|
|
|
c47604 |
bool UdpSendQueue::canSentToUdp() const
|
|
|
c47604 |
{ return connection.udpActive && (busyFirst || connection.tcpRecvQueue.busySize()); }
|
|
|
c47604 |
|
|
|
c47604 |
|
|
|
c47604 |
void UdpSendQueue::whenWriteToUdp(Time &t) const {
|
|
|
c47604 |
int size = connection.tcpRecvQueue.busySize();
|
|
|
c47604 |
if (size >= PACKET_SIZE) {
|
|
|
c47604 |
if (timeLess(nextSendTime, t)) t = nextSendTime;
|
|
|
c47604 |
return;
|
|
|
c47604 |
}
|
|
|
c47604 |
|
|
|
c47604 |
Time tt = t;
|
|
|
c47604 |
if (size > 0 && timeLess(nextPartialSendTime, tt)) tt = nextPartialSendTime;
|
|
|
c47604 |
if (timeLess(busyFirst->resendTime, tt)) tt = busyFirst->resendTime;
|
|
|
c47604 |
if (timeLess(tt, nextSendTime)) tt = nextSendTime;
|
|
|
c47604 |
if (timeLess(t, tt)) t = tt;
|
|
|
c47604 |
}
|