Blame udpsendqueue.cpp

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;
0da3a9
	e->prev = busyLast;
0da3a9
	e->next = nullptr;
0da3a9
	(e->prev ? e->prev->next : busyFirst) = e;
0da3a9
	busyLast = e;
0da3a9
	return e;
0da3a9
}
0da3a9
0da3a9
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
0da3a9
bool UdpSendQueue::sendUdp() {
0da3a9
	Time time = connection.tunnel.time;
0da3a9
	if (timeLess(time, nextSendTime))
0da3a9
		return false;
0da3a9
	
0da3a9
	Entry *e = busyFirst;
0da3a9
	while(e) {
0da3a9
		if (timeLequal(e->resendTime, time))
0da3a9
			break;
0da3a9
		e = e->next;
0da3a9
	}
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;
0da3a9
	packet.init(connection.id, e->index, CMD_DATA, e->size);
0da3a9
	if (e->size) memcpy(packet.payload, e->data, e->size);
0da3a9
	connection.tunnel.udpSend(packet);
0da3a9
	
0da3a9
	e->resendTime = time + connection.tunnel.udpResendDuration;
0da3a9
	nextSendTime += connection.tunnel.udpPartialSendDuration;
0da3a9
	nextPartialSendTime = time + connection.tunnel.udpPartialSendDuration;
0da3a9
	return true;
0da3a9
}
0da3a9