Example #1
0
// return a free acknum and copy netbuffer in the ackpak table
static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer)
{
	node_t *node = &nodes[doomcom->remotenode];
	INT32 i, numfreeslote = 0;

	if (cmpack((UINT8)((node->remotefirstack + MAXACKTOSEND) % 256), node->nextacknum) < 0)
	{
		DEBFILE(va("too fast %d %d\n",node->remotefirstack,node->nextacknum));
		return false;
	}

	for (i = 0; i < MAXACKPACKETS; i++)
		if (!ackpak[i].acknum)
		{
			// for low priority packet, make sure let freeslotes so urgents packets can be sent
			numfreeslote++;
			if (netbuffer->packettype >= PT_CANFAIL && numfreeslote < URGENTFREESLOTENUM)
				continue;

			ackpak[i].acknum = node->nextacknum;
			ackpak[i].nextacknum = node->nextacknum;
			node->nextacknum++;
			if (!node->nextacknum)
				node->nextacknum++;
			ackpak[i].destinationnode = (UINT8)(node - nodes);
			ackpak[i].length = doomcom->datalength;
			if (lowtimer)
			{
				// lowtime mean can't be sent now so try it soon as possible
				ackpak[i].senttime = 0;
				ackpak[i].resentnum = 1;
			}
			else
			{
				ackpak[i].senttime = I_GetTime();
				ackpak[i].resentnum = 0;
			}
			M_Memcpy(ackpak[i].pak.raw, netbuffer, ackpak[i].length);

			*freeack = ackpak[i].acknum;

			sendackpacket++; // for stat

			return true;
		}
#ifdef PARANOIA
	if (devparm)
		I_OutputMsg("No more free ackpacket\n");
#endif
	if (netbuffer->packettype < PT_CANFAIL)
		I_Error("Connection lost\n");
	return false;
}
Example #2
0
static void GotAcks(void)
{
	INT32 i, j;

	for (j = 0; j < MAXACKTOSEND; j++)
		if (netbuffer->u.textcmd[j])
			for (i = 0; i < MAXACKPACKETS; i++)
				if (ackpak[i].acknum && ackpak[i].destinationnode == doomcom->remotenode)
				{
					if (ackpak[i].acknum == netbuffer->u.textcmd[j])
						Removeack(i);
					else
						// nextacknum is first equal to acknum, then when receiving bigger ack
						// there is big chance the packet is lost
						// when resent, nextacknum = nodes[node].nextacknum
						//    will redo the same but with different value
					if (cmpack(ackpak[i].nextacknum, netbuffer->u.textcmd[j]) <= 0
						&& ackpak[i].senttime > 0)
					{
						ackpak[i].senttime--; // hurry up
					}
				}
}
Example #3
0
// we have got a packet proceed the ack request and ack return
static boolean Processackpak(void)
{
	INT32 i;
	boolean goodpacket = true;
	node_t *node = &nodes[doomcom->remotenode];

	// received an ack return, so remove the ack in the list
	if (netbuffer->ackreturn && cmpack(node->remotefirstack, netbuffer->ackreturn) < 0)
	{
		node->remotefirstack = netbuffer->ackreturn;
		// search the ackbuffer and free it
		for (i = 0; i < MAXACKPACKETS; i++)
			if (ackpak[i].acknum && ackpak[i].destinationnode == node - nodes
				&& cmpack(ackpak[i].acknum, netbuffer->ackreturn) <= 0)
			{
				Removeack(i);
			}
	}

	// received a packet with ack, queue it to send the ack back
	if (netbuffer->ack)
	{
		UINT8 ack = netbuffer->ack;
		getackpacket++;
		if (cmpack(ack, node->firstacktosend) <= 0)
		{
			DEBFILE(va("Discard(1) ack %d (duplicated)\n", ack));
			duppacket++;
			goodpacket = false; // discard packet (duplicate)
		}
		else
		{
			// check if it is not already in the queue
			for (i = node->acktosend_tail; i != node->acktosend_head; i = (i+1) % MAXACKTOSEND)
				if (node->acktosend[i] == ack)
				{
					DEBFILE(va("Discard(2) ack %d (duplicated)\n", ack));
					duppacket++;
					goodpacket = false; // discard packet (duplicate)
					break;
				}
			if (goodpacket)
			{
				// is a good packet so increment the acknowledge number,
				// then search for a "hole" in the queue
				UINT8 nextfirstack = (UINT8)(node->firstacktosend + 1);
				if (!nextfirstack)
					nextfirstack = 1;

				if (ack == nextfirstack)
				{
					UINT8 hm1; // head - 1
					boolean change = true;

					node->firstacktosend = nextfirstack++;
					if (!nextfirstack)
						nextfirstack = 1;
					hm1 = (UINT8)((node->acktosend_head-1+MAXACKTOSEND) % MAXACKTOSEND);
					while (change)
					{
						change = false;
						for (i = node->acktosend_tail; i != node->acktosend_head;
							i = (i+1) % MAXACKTOSEND)
						{
							if (cmpack(node->acktosend[i], nextfirstack) <= 0)
							{
								if (node->acktosend[i] == nextfirstack)
								{
									node->firstacktosend = nextfirstack++;
									if (!nextfirstack)
										nextfirstack = 1;
									change = true;
								}
								if (i == node->acktosend_tail)
								{
									node->acktosend[node->acktosend_tail] = 0;
									node->acktosend_tail = (UINT8)((i+1) % MAXACKTOSEND);
								}
								else if (i == hm1)
								{
									node->acktosend[hm1] = 0;
									node->acktosend_head = hm1;
									hm1 = (UINT8)((hm1-1+MAXACKTOSEND) % MAXACKTOSEND);
								}
							}
						}
					}
				}
				else // out of order packet
				{
					// don't increment firsacktosend, put it in asktosend queue
					// will be incremented when the nextfirstack comes (code above)
					UINT8 newhead = (UINT8)((node->acktosend_head+1) % MAXACKTOSEND);
					DEBFILE(va("out of order packet (%d expected)\n", nextfirstack));
					if (newhead != node->acktosend_tail)
					{
						node->acktosend[node->acktosend_head] = ack;
						node->acktosend_head = newhead;
					}
					else // buffer full discard packet, sender will resend it
					{ // we can admit the packet but we will not detect the duplication after :(
						DEBFILE("no more freeackret\n");
						goodpacket = false;
					}
				}
			}
		}
	}
	return goodpacket;
}