(Hopefully) Fix chatbug
after weeks of debugging with the help of a public server, i can finally say with confidence that this should fix chatbug. this bug has been notorious for it's inconsistency, and with the help of the -debugfile
parameter, i've found that the reason is much more low-level than most of us would've probably have guessed.
the cause has to do with how the server sends ACK's back to the client in combination with duplicate packets. normally, how it works is that if a reliable packet is sent over netcode, the client will add it to the netbuffer with some additional data to keep track of which packets has been sent. then, the client waits until the server sends back an ACK corresponding to that packet, and if it fails to get one, it will try to send it again. with that, it also ensures that packets are sent in the order specified, by only sending the oldest non-ACK'ed packet to the server and queues up other packets that comes after it.
here's where things go wrong: if a packet successfully reaches the server but the ACK doesn't reach the client, the client will not be aware that it was processed successfully by the server. this will cause it to resend the same packet, but due to how netcode handles duplicate packets, the next packet will be ignored. the result is that another ACK will never be sent to the client, causing it to lock up as the client repeatedly tries to send the same packet over and over again in hopes that the server will eventually respond to it. this is also the reason why the chat is flooded after a chatbugged client leaves the server, since SRB2 currently has special logic for players leaving the server that causes the server to send 2 ACK's back unconditionally, thus unlocking the client's netbuffer and causing it to send all the packets that were locked in the queue immediately.
the fix here is simply by sending an empty ACK back whenever we get a duplicate packet. while this is not the most elegant solution since it might cause the server to send duplicate ACK's, it seems to solve the problem from my testing. i also want to thank all of the players that joined the debug server that i hosted to track this damn thing down; finding this would not have been possible if it weren't for their help.