Skip to content
Snippets Groups Projects
Commit 0e992ec5 authored by Lactozilla's avatar Lactozilla :speech_balloon:
Browse files

Merge branch 'push-back-acktosend' into 'next'

Clean up d_net.c and push back missed acks to acktosend (Chatbug attempt 3)

See merge request !2591
parents a2aaa45d 499ccdb8
No related branches found
No related tags found
No related merge requests found
...@@ -163,12 +163,6 @@ typedef struct ...@@ -163,12 +163,6 @@ typedef struct
// ack return to send (like sliding window protocol) // ack return to send (like sliding window protocol)
UINT8 firstacktosend; UINT8 firstacktosend;
// when no consecutive packets are received we keep in mind what packets
// we already received in a queue
UINT8 acktosend_head;
UINT8 acktosend_tail;
UINT8 acktosend[MAXACKTOSEND];
// automatically send keep alive packet when not enough trafic // automatically send keep alive packet when not enough trafic
tic_t lasttimeacktosend_sent; tic_t lasttimeacktosend_sent;
// detect connection lost // detect connection lost
...@@ -200,10 +194,9 @@ FUNCMATH static INT32 cmpack(UINT8 a, UINT8 b) ...@@ -200,10 +194,9 @@ FUNCMATH static INT32 cmpack(UINT8 a, UINT8 b)
/** Sets freeack to a free acknum and copies the netbuffer in the ackpak table /** Sets freeack to a free acknum and copies the netbuffer in the ackpak table
* *
* \param freeack The address to store the free acknum at * \param freeack The address to store the free acknum at
* \param lowtimer ???
* \return True if a free acknum was found * \return True if a free acknum was found
*/ */
static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer) static boolean GetFreeAcknum(UINT8 *freeack)
{ {
node_t *node = &nodes[doomcom->remotenode]; node_t *node = &nodes[doomcom->remotenode];
INT32 numfreeslot = 0; INT32 numfreeslot = 0;
...@@ -232,17 +225,8 @@ static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer) ...@@ -232,17 +225,8 @@ static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer)
node->nextacknum++; node->nextacknum++;
ackpak[i].destinationnode = (UINT8)(node - nodes); ackpak[i].destinationnode = (UINT8)(node - nodes);
ackpak[i].length = doomcom->datalength; ackpak[i].length = doomcom->datalength;
if (lowtimer)
{
// Lowtime means can't be sent now so try it as soon as possible
ackpak[i].senttime = 0;
ackpak[i].resentnum = 1;
}
else
{
ackpak[i].senttime = I_GetTime(); ackpak[i].senttime = I_GetTime();
ackpak[i].resentnum = 0; ackpak[i].resentnum = 0;
}
M_Memcpy(ackpak[i].pak.raw, netbuffer, ackpak[i].length); M_Memcpy(ackpak[i].pak.raw, netbuffer, ackpak[i].length);
*freeack = ackpak[i].acknum; *freeack = ackpak[i].acknum;
...@@ -259,38 +243,6 @@ static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer) ...@@ -259,38 +243,6 @@ static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer)
return false; return false;
} }
/** Counts how many acks are free
*
* \param urgent True if the type of the packet meant to
* use an ack is lower than PT_CANFAIL
* If for some reason you don't want use it
* for any packet type in particular,
* just set to false
* \return The number of free acks
*
*/
INT32 Net_GetFreeAcks(boolean urgent)
{
INT32 numfreeslot = 0;
INT32 n = 0; // Number of free acks found
for (INT32 i = 0; i < MAXACKPACKETS; i++)
if (!ackpak[i].acknum)
{
// For low priority packets, make sure to let freeslots so urgent packets can be sent
if (!urgent)
{
numfreeslot++;
if (numfreeslot <= URGENTFREESLOTNUM)
continue;
}
n++;
}
return n;
}
// Get a ack to send in the queue of this node // Get a ack to send in the queue of this node
static UINT8 GetAcktosend(INT32 node) static UINT8 GetAcktosend(INT32 node)
{ {
...@@ -308,9 +260,9 @@ static void RemoveAck(INT32 i) ...@@ -308,9 +260,9 @@ static void RemoveAck(INT32 i)
} }
// We have got a packet, proceed the ack request and ack return // We have got a packet, proceed the ack request and ack return
static int Processackpak(void) static boolean Processackpak(void)
{ {
int goodpacket = 0; boolean goodpacket = true;
node_t *node = &nodes[doomcom->remotenode]; node_t *node = &nodes[doomcom->remotenode];
// Received an ack return, so remove the ack in the list // Received an ack return, so remove the ack in the list
...@@ -319,7 +271,7 @@ static int Processackpak(void) ...@@ -319,7 +271,7 @@ static int Processackpak(void)
node->remotefirstack = netbuffer->ackreturn; node->remotefirstack = netbuffer->ackreturn;
// Search the ackbuffer and free it // Search the ackbuffer and free it
for (INT32 i = 0; i < MAXACKPACKETS; i++) for (INT32 i = 0; i < MAXACKPACKETS; i++)
if (ackpak[i].acknum && ackpak[i].destinationnode == node - nodes if (ackpak[i].acknum && ackpak[i].destinationnode == doomcom->remotenode
&& cmpack(ackpak[i].acknum, netbuffer->ackreturn) <= 0) && cmpack(ackpak[i].acknum, netbuffer->ackreturn) <= 0)
{ {
RemoveAck(i); RemoveAck(i);
...@@ -335,20 +287,9 @@ static int Processackpak(void) ...@@ -335,20 +287,9 @@ static int Processackpak(void)
{ {
DEBFILE(va("Discard(1) ack %d (duplicated)\n", ack)); DEBFILE(va("Discard(1) ack %d (duplicated)\n", ack));
duppacket++; duppacket++;
goodpacket = 1; // Discard packet (duplicate) goodpacket = false; // Discard packet (duplicate)
} }
else else
{
// Check if it is not already in the queue
for (INT32 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 = 1; // Discard packet (duplicate)
break;
}
if (goodpacket == 0)
{ {
// Is a good packet so increment the acknowledge number, // Is a good packet so increment the acknowledge number,
// Then search for a "hole" in the queue // Then search for a "hole" in the queue
...@@ -358,96 +299,20 @@ static int Processackpak(void) ...@@ -358,96 +299,20 @@ static int Processackpak(void)
if (ack == nextfirstack) if (ack == nextfirstack)
{ {
UINT8 hm1; // head - 1 node->firstacktosend = nextfirstack;
boolean change = true;
node->firstacktosend = nextfirstack++;
if (!nextfirstack)
nextfirstack = 1;
hm1 = (UINT8)((node->acktosend_head-1+MAXACKTOSEND) % MAXACKTOSEND);
while (change)
{
change = false;
for (INT32 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 else // Out of order packet
{ {
// Don't increment firsacktosend, put it in asktosend queue // Don't increment firsacktosend, put it in asktosend queue
// Will be incremented when the nextfirstack comes (code above) // 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)); DEBFILE(va("out of order packet (%d expected)\n", nextfirstack));
if (newhead != node->acktosend_tail) goodpacket = false;
{
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 = 2;
} }
} }
}
}
}
// return values: 0 = ok, 1 = duplicate, 2 = out of order
return goodpacket; return goodpacket;
} }
// send special packet with only ack on it
void Net_SendAcks(INT32 node)
{
netbuffer->packettype = PT_NOTHING;
M_Memcpy(netbuffer->u.textcmd, nodes[node].acktosend, MAXACKTOSEND);
HSendPacket(node, false, 0, MAXACKTOSEND);
}
static void GotAcks(void)
{
for (INT32 j = 0; j < MAXACKTOSEND; j++)
if (netbuffer->u.textcmd[j])
for (INT32 i = 0; i < MAXACKPACKETS; i++)
if (ackpak[i].acknum && ackpak[i].destinationnode == doomcom->remotenode)
{
if (ackpak[i].acknum == netbuffer->u.textcmd[j])
RemoveAck(i);
// 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
else if (cmpack(ackpak[i].nextacknum, netbuffer->u.textcmd[j]) <= 0
&& ackpak[i].senttime > 0)
{
ackpak[i].senttime--; // hurry up
}
}
}
void Net_ConnectionTimeout(INT32 node) void Net_ConnectionTimeout(INT32 node)
{ {
// Don't timeout several times // Don't timeout several times
...@@ -501,11 +366,6 @@ void Net_AckTicker(void) ...@@ -501,11 +366,6 @@ void Net_AckTicker(void)
// This is something like node open flag // This is something like node open flag
if (nodes[i].firstacktosend) if (nodes[i].firstacktosend)
{ {
// We haven't sent a packet for a long time
// Acknowledge packet if needed
if (nodes[i].lasttimeacktosend_sent + ACKTOSENDTIMEOUT < I_GetTime())
Net_SendAcks(i);
if (!(nodes[i].flags & NF_CLOSE) if (!(nodes[i].flags & NF_CLOSE)
&& nodes[i].lasttimepacketreceived + connectiontimeout < I_GetTime()) && nodes[i].lasttimepacketreceived + connectiontimeout < I_GetTime())
{ {
...@@ -519,38 +379,13 @@ void Net_AckTicker(void) ...@@ -519,38 +379,13 @@ void Net_AckTicker(void)
// (the higher layer doesn't have room, or something else ....) // (the higher layer doesn't have room, or something else ....)
void Net_UnAcknowledgePacket(INT32 node) void Net_UnAcknowledgePacket(INT32 node)
{ {
INT32 hm1 = (nodes[node].acktosend_head-1+MAXACKTOSEND) % MAXACKTOSEND;
DEBFILE(va("UnAcknowledge node %d\n", node)); DEBFILE(va("UnAcknowledge node %d\n", node));
if (!node) if (!node)
return; return;
if (nodes[node].acktosend[hm1] == netbuffer->ack)
{
nodes[node].acktosend[hm1] = 0;
nodes[node].acktosend_head = (UINT8)hm1;
}
else if (nodes[node].firstacktosend == netbuffer->ack)
{
nodes[node].firstacktosend--; nodes[node].firstacktosend--;
if (!nodes[node].firstacktosend) if (!nodes[node].firstacktosend)
nodes[node].firstacktosend = UINT8_MAX; nodes[node].firstacktosend = UINT8_MAX;
} }
else
{
while (nodes[node].firstacktosend != netbuffer->ack)
{
nodes[node].acktosend_tail = (UINT8)
((nodes[node].acktosend_tail-1+MAXACKTOSEND) % MAXACKTOSEND);
nodes[node].acktosend[nodes[node].acktosend_tail] = nodes[node].firstacktosend;
nodes[node].firstacktosend--;
if (!nodes[node].firstacktosend)
nodes[node].firstacktosend = UINT8_MAX;
}
nodes[node].firstacktosend++;
if (!nodes[node].firstacktosend)
nodes[node].firstacktosend = 1;
}
}
/** Checks if all acks have been received /** Checks if all acks have been received
* *
...@@ -592,7 +427,6 @@ void Net_WaitAllAckReceived(UINT32 timeout) ...@@ -592,7 +427,6 @@ void Net_WaitAllAckReceived(UINT32 timeout)
static void InitNode(node_t *node) static void InitNode(node_t *node)
{ {
node->acktosend_head = node->acktosend_tail = 0;
node->firstacktosend = 0; node->firstacktosend = 0;
node->nextacknum = 1; node->nextacknum = 1;
node->remotefirstack = 0; node->remotefirstack = 0;
...@@ -651,11 +485,11 @@ void Net_CloseConnection(INT32 node) ...@@ -651,11 +485,11 @@ void Net_CloseConnection(INT32 node)
nodes[node].flags |= NF_CLOSE; nodes[node].flags |= NF_CLOSE;
// try to Send ack back (two army problem) if (nodes[node].firstacktosend)
if (GetAcktosend(node))
{ {
Net_SendAcks(node); // send a PT_NOTHING back to acknowledge the packet
Net_SendAcks(node); netbuffer->packettype = PT_NOTHING;
HSendPacket(node, false, 0, 0);
} }
// check if we are waiting for an ack from this node // check if we are waiting for an ack from this node
...@@ -991,7 +825,7 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen ...@@ -991,7 +825,7 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen
netbuffer->ackreturn = 0; netbuffer->ackreturn = 0;
if (reliable) if (reliable)
{ {
if (!GetFreeAcknum(&netbuffer->ack, false)) if (!GetFreeAcknum(&netbuffer->ack))
return false; return false;
} }
else else
...@@ -1057,7 +891,6 @@ boolean HGetPacket(void) ...@@ -1057,7 +891,6 @@ boolean HGetPacket(void)
while(true) while(true)
{ {
//nodejustjoined = I_NetGet(); //nodejustjoined = I_NetGet();
int goodpacket;
I_NetGet(); I_NetGet();
if (doomcom->remotenode == -1) // No packet received if (doomcom->remotenode == -1) // No packet received
...@@ -1103,22 +936,12 @@ boolean HGetPacket(void) ...@@ -1103,22 +936,12 @@ boolean HGetPacket(void)
}*/ }*/
// Proceed the ack and ackreturn field // Proceed the ack and ackreturn field
goodpacket = Processackpak(); if (!Processackpak())
if (goodpacket != 0)
{
// resend the ACK in case the previous ACK didn't reach the client.
// prevents the client's netbuffer from locking up.
if (goodpacket == 1)
Net_SendAcks(doomcom->remotenode);
continue; // discarded (duplicated) continue; // discarded (duplicated)
}
// A packet with just ackreturn // A packet with just ackreturn
if (netbuffer->packettype == PT_NOTHING) if (netbuffer->packettype == PT_NOTHING)
{
GotAcks();
continue; continue;
}
break; break;
} }
......
...@@ -60,7 +60,6 @@ extern netnode_t netnodes[MAXNETNODES]; ...@@ -60,7 +60,6 @@ extern netnode_t netnodes[MAXNETNODES];
extern boolean serverrunning; extern boolean serverrunning;
INT32 Net_GetFreeAcks(boolean urgent);
void Net_AckTicker(void); void Net_AckTicker(void);
// If reliable return true if packet sent, 0 else // If reliable return true if packet sent, 0 else
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment