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 STJr/SRB2!2591
parents a2aaa45d 499ccdb8
Branches
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