]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - netconn.c
New rate burst handling; cvars: cl_rate_burstsize, net_usesizelimit, net_burstreserve
[xonotic/darkplaces.git] / netconn.c
index aa8bf94aeef06c1447d8fc62d5fd1c74fcb96596..abc3501e0a23960f8f2171899f81dc98b65347d6 100755 (executable)
--- a/netconn.c
+++ b/netconn.c
@@ -76,6 +76,9 @@ static unsigned char sv_message_buf[NET_MAXMESSAGE];
 char cl_readstring[MAX_INPUTLINE];
 char sv_readstring[MAX_INPUTLINE];
 
+cvar_t net_test = {0, "net_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
+cvar_t net_usesizelimit = {0, "net_usesizelimit", "2", "use packet size limiting (0: never, 1: in non-CSQC mode, 2: always)"};
+cvar_t net_burstreserve = {0, "net_burstreserve", "0.3", "how much of the burst time to reserve for packet size spikes"};
 cvar_t net_messagetimeout = {0, "net_messagetimeout","300", "drops players who have not sent any packets for this many seconds"};
 cvar_t net_connecttimeout = {0, "net_connecttimeout","15", "after requesting a connection, the client must reply within this many seconds or be dropped (cuts down on connect floods). Must be above 10 seconds."};
 cvar_t net_connectfloodblockingtimeout = {0, "net_connectfloodblockingtimeout", "5", "when a connection packet is received, it will block all future connect packets from that IP address for this many seconds (cuts down on connect floods). Note that this does not include retries from the same IP; these are handled earlier and let in."};
@@ -655,6 +658,7 @@ qboolean NetConn_CanSend(netconn_t *conn)
        conn->outgoing_netgraph[conn->outgoing_packetcounter].unreliablebytes = NETGRAPH_NOPACKET;
        conn->outgoing_netgraph[conn->outgoing_packetcounter].reliablebytes   = NETGRAPH_NOPACKET;
        conn->outgoing_netgraph[conn->outgoing_packetcounter].ackbytes        = NETGRAPH_NOPACKET;
+       conn->outgoing_netgraph[conn->outgoing_packetcounter].cleartime       = conn->cleartime;
        if (realtime > conn->cleartime)
                return true;
        else
@@ -664,7 +668,24 @@ qboolean NetConn_CanSend(netconn_t *conn)
        }
 }
 
-int NetConn_SendUnreliableMessage(netconn_t *conn, sizebuf_t *data, protocolversion_t protocol, int rate, qboolean quakesignon_suppressreliables)
+void NetConn_UpdateCleartime(double *cleartime, int rate, int burstsize, int len)
+{
+       double bursttime = burstsize / (double)rate;
+
+       // delay later packets to obey rate limit
+       if (*cleartime < realtime - bursttime)
+               *cleartime = realtime - bursttime;
+       *cleartime = *cleartime + len / (double)rate;
+
+       // limit bursts to one packet in size ("dialup mode" emulating old behaviour)
+       if (net_test.integer)
+       {
+               if (*cleartime < realtime)
+                       *cleartime = realtime;
+       }
+}
+
+int NetConn_SendUnreliableMessage(netconn_t *conn, sizebuf_t *data, protocolversion_t protocol, int rate, int burstsize, qboolean quakesignon_suppressreliables)
 {
        int totallen = 0;
        unsigned char sendbuffer[NET_HEADERSIZE+NET_MAXMESSAGE];
@@ -676,6 +697,8 @@ int NetConn_SendUnreliableMessage(netconn_t *conn, sizebuf_t *data, protocolvers
        if (conn->outgoing_netgraph[conn->outgoing_packetcounter].unreliablebytes == NETGRAPH_CHOKEDPACKET)
                conn->outgoing_netgraph[conn->outgoing_packetcounter].unreliablebytes = NETGRAPH_NOPACKET;
 
+       conn->outgoing_netgraph[conn->outgoing_packetcounter].cleartime = conn->cleartime;
+
        if (protocol == PROTOCOL_QUAKEWORLD)
        {
                int packetLen;
@@ -865,12 +888,7 @@ int NetConn_SendUnreliableMessage(netconn_t *conn, sizebuf_t *data, protocolvers
                }
        }
 
-       // delay later packets to obey rate limit
-       if (conn->cleartime < realtime - 0.1)
-               conn->cleartime = realtime - 0.1;
-       conn->cleartime = conn->cleartime + (double)totallen / (double)rate;
-       if (conn->cleartime < realtime)
-               conn->cleartime = realtime;
+       NetConn_UpdateCleartime(&conn->cleartime, cl_rate.integer, cl_rate_burstsize.integer, totallen);
 
        return 0;
 }
@@ -1191,6 +1209,7 @@ static int NetConn_ReceivedMessage(netconn_t *conn, const unsigned char *data, s
                        {
                                conn->incoming_packetcounter = (conn->incoming_packetcounter + 1) % NETGRAPH_PACKETS;
                                conn->incoming_netgraph[conn->incoming_packetcounter].time            = realtime;
+                               conn->incoming_netgraph[conn->incoming_packetcounter].cleartime       = conn->incoming_cleartime;
                                conn->incoming_netgraph[conn->incoming_packetcounter].unreliablebytes = NETGRAPH_LOSTPACKET;
                                conn->incoming_netgraph[conn->incoming_packetcounter].reliablebytes   = NETGRAPH_NOPACKET;
                                conn->incoming_netgraph[conn->incoming_packetcounter].ackbytes        = NETGRAPH_NOPACKET;
@@ -1198,9 +1217,19 @@ static int NetConn_ReceivedMessage(netconn_t *conn, const unsigned char *data, s
                }
                conn->incoming_packetcounter = (conn->incoming_packetcounter + 1) % NETGRAPH_PACKETS;
                conn->incoming_netgraph[conn->incoming_packetcounter].time            = realtime;
+               conn->incoming_netgraph[conn->incoming_packetcounter].cleartime       = conn->incoming_cleartime;
                conn->incoming_netgraph[conn->incoming_packetcounter].unreliablebytes = originallength + 28;
                conn->incoming_netgraph[conn->incoming_packetcounter].reliablebytes   = NETGRAPH_NOPACKET;
                conn->incoming_netgraph[conn->incoming_packetcounter].ackbytes        = NETGRAPH_NOPACKET;
+               NetConn_UpdateCleartime(&conn->incoming_cleartime, cl_rate.integer, cl_rate_burstsize.integer, originallength + 28);
+
+               // limit bursts to one packet in size ("dialup mode" emulating old behaviour)
+               if (net_test.integer)
+               {
+                       if (conn->cleartime < realtime)
+                               conn->cleartime = realtime;
+               }
+
                if (reliable_ack == conn->qw.reliable_sequence)
                {
                        // received, now we will be able to send another reliable message
@@ -1270,6 +1299,7 @@ static int NetConn_ReceivedMessage(netconn_t *conn, const unsigned char *data, s
                                                {
                                                        conn->incoming_packetcounter = (conn->incoming_packetcounter + 1) % NETGRAPH_PACKETS;
                                                        conn->incoming_netgraph[conn->incoming_packetcounter].time            = realtime;
+                                                       conn->incoming_netgraph[conn->incoming_packetcounter].cleartime       = conn->incoming_cleartime;
                                                        conn->incoming_netgraph[conn->incoming_packetcounter].unreliablebytes = NETGRAPH_LOSTPACKET;
                                                        conn->incoming_netgraph[conn->incoming_packetcounter].reliablebytes   = NETGRAPH_NOPACKET;
                                                        conn->incoming_netgraph[conn->incoming_packetcounter].ackbytes        = NETGRAPH_NOPACKET;
@@ -1277,9 +1307,12 @@ static int NetConn_ReceivedMessage(netconn_t *conn, const unsigned char *data, s
                                        }
                                        conn->incoming_packetcounter = (conn->incoming_packetcounter + 1) % NETGRAPH_PACKETS;
                                        conn->incoming_netgraph[conn->incoming_packetcounter].time            = realtime;
+                                       conn->incoming_netgraph[conn->incoming_packetcounter].cleartime       = conn->incoming_cleartime;
                                        conn->incoming_netgraph[conn->incoming_packetcounter].unreliablebytes = originallength + 28;
                                        conn->incoming_netgraph[conn->incoming_packetcounter].reliablebytes   = NETGRAPH_NOPACKET;
                                        conn->incoming_netgraph[conn->incoming_packetcounter].ackbytes        = NETGRAPH_NOPACKET;
+                                       NetConn_UpdateCleartime(&conn->incoming_cleartime, cl_rate.integer, cl_rate_burstsize.integer, originallength + 28);
+
                                        conn->nq.unreliableReceiveSequence = sequence + 1;
                                        conn->lastMessageTime = realtime;
                                        conn->timeout = realtime + newtimeout;
@@ -1308,6 +1341,8 @@ static int NetConn_ReceivedMessage(netconn_t *conn, const unsigned char *data, s
                        else if (flags & NETFLAG_ACK)
                        {
                                conn->incoming_netgraph[conn->incoming_packetcounter].ackbytes += originallength + 28;
+                               NetConn_UpdateCleartime(&conn->incoming_cleartime, cl_rate.integer, cl_rate_burstsize.integer, originallength + 28);
+
                                if (sequence == (conn->nq.sendSequence - 1))
                                {
                                        if (sequence == conn->nq.ackSequence)
@@ -1366,7 +1401,10 @@ static int NetConn_ReceivedMessage(netconn_t *conn, const unsigned char *data, s
                        {
                                unsigned char temppacket[8];
                                conn->incoming_netgraph[conn->incoming_packetcounter].reliablebytes   += originallength + 28;
+                               NetConn_UpdateCleartime(&conn->incoming_cleartime, cl_rate.integer, cl_rate_burstsize.integer, originallength + 28);
+
                                conn->outgoing_netgraph[conn->outgoing_packetcounter].ackbytes        += 8 + 28;
+
                                StoreBigLong(temppacket, 8 | NETFLAG_ACK);
                                StoreBigLong(temppacket + 4, sequence);
                                sendme = Crypto_EncryptPacket(&conn->crypto, temppacket, 8, &cryptosendbuffer, &sendmelen, sizeof(cryptosendbuffer));
@@ -1468,7 +1506,7 @@ static void NetConn_ConnectionEstablished(lhnetsocket_t *mysocket, lhnetaddress_
                msg.data = buf;
                msg.maxsize = sizeof(buf);
                MSG_WriteChar(&msg, clc_nop);
-               NetConn_SendUnreliableMessage(cls.netcon, &msg, cls.protocol, 10000, false);
+               NetConn_SendUnreliableMessage(cls.netcon, &msg, cls.protocol, 10000, 0, false);
        }
 }
 
@@ -3681,6 +3719,9 @@ void NetConn_Init(void)
        Cmd_AddCommand("net_slistqw", Net_SlistQW_f, "query qw master servers and print all server information");
        Cmd_AddCommand("net_refresh", Net_Refresh_f, "query dp master servers and refresh all server information");
        Cmd_AddCommand("heartbeat", Net_Heartbeat_f, "send a heartbeat to the master server (updates your server information)");
+       Cvar_RegisterVariable(&net_test);
+       Cvar_RegisterVariable(&net_usesizelimit);
+       Cvar_RegisterVariable(&net_burstreserve);
        Cvar_RegisterVariable(&rcon_restricted_password);
        Cvar_RegisterVariable(&rcon_restricted_commands);
        Cvar_RegisterVariable(&rcon_secure_maxdiff);