Blame udpsendqueue.cpp

0da3a9
0da3a9
#include <cstring></cstring>
0da3a9
0da3a9
#include "tunnel.h"
0da3a9
#include "connection.h"
0da3a9
#include "udpsendqueue.h"
0da3a9
0da3a9
460064
//#define DebugMsg HideDebugMSG
460064
#define DebugMsg ShowDebugMSG
460064
460064
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;
460064
	busyFirst = 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;
406f13
	busyLast = 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) {
460064
	DebugMsg("%u, %u, %s", connection.id.id, index, bitsToString(bits, bitsCount ? (bitsCount-1)/8 + 1 : 0));
0da3a9
	Entry *e = busyFirst;
0da3a9
	while(e) {
406f13
		if (cycleLequal(index, e->index)) {
460064
			unsigned int bit = e->index - index;
406f13
			if (bit >= bitsCount)
406f13
				{ e = e->next; continue; }
460064
			unsigned int byte = bit / 8;
460064
			bit %= 8;
460064
			if ( !(bits[byte] & (1 << bit)) )
460064
				{ e = e->next; continue; }
0da3a9
		}
460064
		
460064
		DebugMsg("%u, %u - confirmed", connection.id.id, e->index);
460064
		Entry *ee = e;
460064
		e = e->next;
460064
		freeEntry(ee);
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;
406f13
	if (e && timeLess(time, e->resendTime))
c47604
		e = nullptr;
0da3a9
	
346c39
	if (!e && freeFirst && !finalEntryAdded) {
0da3a9
		int size = connection.tcpRecvQueue.busySize();
0da3a9
		if (size > PACKET_SIZE) size = PACKET_SIZE;
0da3a9
		if (size < 0) size = 0;
0da3a9
		
1d16df
		bool load = true;
0da3a9
		if (size == 0) {
1d16df
			if (connection.tcpSockId >= 0) {
0da3a9
				nextPartialSendTime = time + connection.tunnel.udpPartialSendDuration;
1d16df
				load = false;
0da3a9
			}
0da3a9
		} else {
0da3a9
			if (size < PACKET_SIZE && timeLess(time, nextPartialSendTime))
1d16df
				load = false;
0da3a9
		}
0da3a9
		
1d16df
		if (load && (e = allocEntry())) {
1d16df
			nextPartialSendTime = time + connection.tunnel.udpPartialSendDuration;
1d16df
			e->index = nextIndex++;
1d16df
			e->size = size;
1d16df
			if (e->size) connection.tcpRecvQueue.pop(e->data, e->size); else finalEntryAdded = true;
1d16df
			DebugMsg("%u, %u, %d - created packet to send by UDP", connection.id.id, e->index, e->size);
1d16df
		}
0da3a9
	}
0da3a9
	
1d16df
	if (!e) e = busyFirst;
1d16df
	if (!e) return false;
1d16df
	
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);
460064
	DebugMsg("%u, %u, %hu", connection.id.id, e->index, e->size);
c47604
	connection.tunnel.sendUdpPacket(connection.id.address, packet);
0da3a9
	
0da3a9
	e->resendTime = time + connection.tunnel.udpResendDuration;
460064
	nextSendTime += connection.tunnel.udpSendDuration;
1d16df
	
c47604
	moveToEnd(e);
0da3a9
	return true;
0da3a9
}
0da3a9
873e9f
873e9f
int UdpSendQueue::sendUdp() {
346c39
	Time time = connection.tunnel.time;
346c39
	
873e9f
	int sent = 0;
873e9f
	while(sendUdpSingle()) {
873e9f
		++sent;
873e9f
		if (sent == 100) {
346c39
			if (timeLess(nextSendTime, time)) {
1d16df
				DebugMsg( "%u, time correction by %llu after sent %d packets",
346c39
						  connection.id.id, time + 1 - nextSendTime, sent );
346c39
				nextSendTime = time + 1;
1d16df
			}
873e9f
			break;
873e9f
		}
873e9f
	}
346c39
	
346c39
	/*
346c39
	while(timeLequal(nextSendTime, time) && connection.udpRecvQueue.isConfirmRequired()) {
346c39
		if (sent == 100) {
346c39
			DebugMsg( "%u, time correction by %llu after sent %d packets (extra confirmations)",
346c39
					  connection.id.id, time + 1 - nextSendTime, sent );
346c39
			nextSendTime = time + 1;
346c39
			break;
346c39
		}
346c39
		DebugMsg("%u - nothing to send, send confirmation", connection.id.id);
346c39
		connection.udpRecvQueue.sendUdpConfirm(true);
346c39
		nextSendTime += connection.tunnel.udpSendDuration;
346c39
		++sent;
346c39
	}
346c39
	*/
346c39
	
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();
346c39
	if (busyFirst || size >= PACKET_SIZE /*|| connection.udpRecvQueue.isConfirmRequired()*/) {
c47604
		if (timeLess(nextSendTime, t)) t = nextSendTime;
5314e4
	} else
5314e4
	if (size > 0) {
5314e4
		Time tt = nextPartialSendTime;
5314e4
		if (timeLess(nextPartialSendTime, nextSendTime)) tt = nextSendTime;
5314e4
		if (timeLess(tt, t)) t = tt;
c47604
	}
c47604
}