rate limited networking ("rate" command in client console, limited by sv_maxrate...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sat, 21 Feb 2004 11:58:08 +0000 (11:58 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sat, 21 Feb 2004 11:58:08 +0000 (11:58 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@3916 d7cf8633-e32d-0410-b094-e92efae38249

cl_demo.c
cl_parse.c
client.h
host_cmd.c
netconn.c
netconn.h
quakedef.h
server.h
sv_main.c

index 546ce45..78f14fe 100644 (file)
--- a/cl_demo.c
+++ b/cl_demo.c
@@ -168,6 +168,8 @@ void CL_ReadDemoMessage(void)
                // get the next message
                FS_Read(cls.demofile, &net_message.cursize, 4);
                net_message.cursize = LittleLong(net_message.cursize);
+               if (net_message.cursize > net_message.maxsize)
+                       Host_Error("Demo message (%i) > net_message.maxsize (%i)", net_message.cursize, net_message.maxsize);
                VectorCopy(cl.mviewangles[0], cl.mviewangles[1]);
                for (i = 0;i < 3;i++)
                {
@@ -175,8 +177,6 @@ void CL_ReadDemoMessage(void)
                        cl.mviewangles[0][i] = LittleFloat(f);
                }
 
-               if (net_message.cursize > NET_MAXMESSAGE)
-                       Host_Error("Demo message > NET_MAXMESSAGE");
                if (FS_Read(cls.demofile, net_message.data, net_message.cursize) == (size_t)net_message.cursize)
                {
                        MSG_BeginReading();
index 43cb2c2..0a1d5ed 100644 (file)
@@ -290,6 +290,9 @@ Con_DPrintf ("CL_SignonReply: %i\n", cls.signon);
                        MSG_WriteString (&cls.message, va("pmodel %i\n", cl_pmodel.integer));
                }
 
+               MSG_WriteByte (&cls.message, clc_stringcmd);
+               MSG_WriteString (&cls.message, va("rate %i\n", cl_rate.integer));
+
                MSG_WriteByte (&cls.message, clc_stringcmd);
                MSG_WriteString (&cls.message, "spawn");
                break;
index 692b0e5..d7b281b 100644 (file)
--- a/client.h
+++ b/client.h
@@ -454,6 +454,7 @@ extern mempool_t *cl_scores_mempool;
 //
 extern cvar_t cl_name;
 extern cvar_t cl_color;
+extern cvar_t cl_rate;
 extern cvar_t cl_pmodel;
 
 extern cvar_t cl_upspeed;
index 668d30b..3e74ef7 100644 (file)
@@ -930,6 +930,37 @@ void Host_Color_f(void)
        }
 }
 
+cvar_t cl_rate = {CVAR_SAVE, "_cl_rate", "10000"};
+cvar_t sv_maxrate = {CVAR_SAVE | CVAR_NOTIFY, "sv_maxrate", "10000"};
+void Host_Rate_f(void)
+{
+       int rate, maxrate;
+
+       if (Cmd_Argc() != 2)
+       {
+               Con_Printf ("\"rate\" is \"%i\"\n", cl_rate.integer);
+               Con_Printf ("rate <500-25000>\n");
+               return;
+       }
+
+       rate = atoi(Cmd_Argv(1));
+
+       if (cmd_source == src_command)
+       {
+               Cvar_SetValue ("_cl_rate", bound(NET_MINRATE, rate, NET_MAXRATE));
+               if (cls.state == ca_connected)
+                       Cmd_ForwardToServer ();
+               return;
+       }
+
+       maxrate = bound(NET_MINRATE, sv_maxrate.integer, NET_MAXRATE);
+       if (sv_maxrate.integer != maxrate)
+               Cvar_SetValueQuick(&sv_maxrate, maxrate);
+
+       if (LHNETADDRESS_GetAddressType(&host_client->netconnection->peeraddress) != LHNETADDRESSTYPE_LOOP)
+               host_client->netconnection->rate = bound(NET_MINRATE, rate, maxrate);
+}
+
 /*
 ==================
 Host_Kill_f
@@ -1730,6 +1761,9 @@ void Host_InitCommands (void)
        Cmd_AddCommand ("name", Host_Name_f);
        Cvar_RegisterVariable (&cl_color);
        Cmd_AddCommand ("color", Host_Color_f);
+       Cvar_RegisterVariable (&cl_rate);
+       Cmd_AddCommand ("rate", Host_Rate_f);
+       Cvar_RegisterVariable (&sv_maxrate);
        if (gamemode == GAME_NEHAHRA)
        {
                Cvar_RegisterVariable (&cl_pmodel);
index c573bd6..a9c1963 100755 (executable)
--- a/netconn.c
+++ b/netconn.c
@@ -78,8 +78,8 @@ int serverreplycount = 0;
 int hostCacheCount = 0;
 hostcache_t hostcache[HOSTCACHESIZE];
 
-static qbyte sendbuffer[NET_MAXMESSAGE];
-static qbyte readbuffer[NET_MAXMESSAGE];
+static qbyte sendbuffer[NET_HEADERSIZE+NET_MAXMESSAGE];
+static qbyte readbuffer[NET_HEADERSIZE+NET_MAXMESSAGE];
 
 int cl_numsockets;
 lhnetsocket_t *cl_sockets[16];
@@ -163,8 +163,8 @@ int NetConn_SendReliableMessage(netconn_t *conn, sizebuf_t *data)
        if (data->cursize == 0)
                Sys_Error("Datagram_SendMessage: zero length message\n");
 
-       if (data->cursize > NET_MAXMESSAGE)
-               Sys_Error("Datagram_SendMessage: message too big %u\n", data->cursize);
+       if (data->cursize > (int)sizeof(conn->sendMessage))
+               Sys_Error("Datagram_SendMessage: message too big (%u > %u)\n", data->cursize, sizeof(conn->sendMessage));
 
        if (conn->canSend == false)
                Sys_Error("SendMessage: called with canSend == false\n");
@@ -189,7 +189,7 @@ int NetConn_SendReliableMessage(netconn_t *conn, sizebuf_t *data)
        header = (void *)sendbuffer;
        header[0] = BigLong(packetLen | (NETFLAG_DATA | eom));
        header[1] = BigLong(conn->sendSequence);
-       memcpy(sendbuffer + 8, conn->sendMessage, dataLen);
+       memcpy(sendbuffer + NET_HEADERSIZE, conn->sendMessage, dataLen);
 
        conn->sendSequence++;
        conn->canSend = false;
@@ -228,7 +228,7 @@ static void NetConn_SendMessageNext(netconn_t *conn)
                header = (void *)sendbuffer;
                header[0] = BigLong(packetLen | (NETFLAG_DATA | eom));
                header[1] = BigLong(conn->sendSequence);
-               memcpy(sendbuffer + 8, conn->sendMessage, dataLen);
+               memcpy(sendbuffer + NET_HEADERSIZE, conn->sendMessage, dataLen);
 
                conn->sendSequence++;
                conn->sendNext = false;
@@ -266,7 +266,7 @@ static void NetConn_ReSendMessage(netconn_t *conn)
                header = (void *)sendbuffer;
                header[0] = BigLong(packetLen | (NETFLAG_DATA | eom));
                header[1] = BigLong(conn->sendSequence - 1);
-               memcpy(sendbuffer + 8, conn->sendMessage, dataLen);
+               memcpy(sendbuffer + NET_HEADERSIZE, conn->sendMessage, dataLen);
 
                conn->sendNext = false;
 
@@ -288,20 +288,20 @@ int NetConn_SendUnreliableMessage(netconn_t *conn, sizebuf_t *data)
        int packetLen;
        int *header;
 
-#ifdef DEBUG
+       packetLen = NET_HEADERSIZE + data->cursize;
+
+//#ifdef DEBUG
        if (data->cursize == 0)
                Sys_Error("Datagram_SendUnreliableMessage: zero length message\n");
 
-       if (data->cursize > MAX_DATAGRAM)
+       if (packetLen > (int)sizeof(sendbuffer))
                Sys_Error("Datagram_SendUnreliableMessage: message too big %u\n", data->cursize);
-#endif
-
-       packetLen = NET_HEADERSIZE + data->cursize;
+//#endif
 
        header = (void *)sendbuffer;
        header[0] = BigLong(packetLen | NETFLAG_UNRELIABLE);
        header[1] = BigLong(conn->unreliableSendSequence);
-       memcpy(sendbuffer + 8, data->data, data->cursize);
+       memcpy(sendbuffer + NET_HEADERSIZE, data->data, data->cursize);
 
        conn->unreliableSendSequence++;
 
@@ -431,6 +431,11 @@ netconn_t *NetConn_Open(lhnetsocket_t *mysocket, lhnetaddress_t *peeraddress)
        conn = Mem_Alloc(netconn_mempool, sizeof(*conn));
        conn->mysocket = mysocket;
        conn->peeraddress = *peeraddress;
+       // updated by receiving "rate" command from client
+       conn->rate = NET_MINRATE;
+       // no limits for local player
+       if (LHNETADDRESS_GetAddressType(peeraddress) == LHNETADDRESSTYPE_LOOP)
+               conn->rate = 1000000000;
        conn->canSend = true;
        conn->connecttime = realtime;
        conn->lastMessageTime = realtime;
index cc99127..a2ab98f 100755 (executable)
--- a/netconn.h
+++ b/netconn.h
@@ -24,11 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #include "lhnet.h"
 
-#define NET_NAMELEN                    128
-
-#define NET_MAXMESSAGE         65536
 #define NET_HEADERSIZE         (2 * sizeof(unsigned int))
-#define NET_DATAGRAMSIZE       (MAX_DATAGRAM + NET_HEADERSIZE)
 
 // NetHeader flags
 #define NETFLAG_LENGTH_MASK    0x0000ffff
@@ -120,6 +116,9 @@ typedef struct netconn_s
 
        lhnetsocket_t *mysocket;
        lhnetaddress_t peeraddress;
+       
+       // requested rate in bytes per second
+       int rate;
 
        // this is mostly identical to qsocket_t from quake
 
@@ -143,7 +142,7 @@ typedef struct netconn_s
        int receiveMessageLength;
        qbyte receiveMessage[NET_MAXMESSAGE];
 
-       char address[NET_NAMELEN];
+       char address[128];
 } netconn_t;
 
 extern netconn_t *netconn_list;
index 14b431e..107a991 100644 (file)
@@ -46,9 +46,9 @@ extern char *buildstring;
 #define        ON_EPSILON              0.1                     // point on plane side epsilon
 
 #define MAX_PACKETFRAGMENT 1024                // max length of packet fragment
-// LordHavoc: this was 1024, now 65536
-#define        MAX_DATAGRAM    65536           // max length of unreliable
-#define        MAX_NETRELIABLE 65536           // max length of reliable message (fragments into unreliable packets)
+#define NET_MAXMESSAGE 65536
+#define NET_MINRATE            500 // limits "rate" and "sv_maxrate" cvars
+#define NET_MAXRATE            25000 // limits "rate" and "sv_maxrate" cvars
 
 //
 // per-level limits
index de23230..90c42bb 100644 (file)
--- a/server.h
+++ b/server.h
@@ -84,15 +84,15 @@ typedef struct
        server_state_t state;
 
        sizebuf_t datagram;
-       qbyte datagram_buf[MAX_DATAGRAM];
+       qbyte datagram_buf[NET_MAXMESSAGE];
 
        // copied to all clients at end of frame
        sizebuf_t reliable_datagram;
-       qbyte reliable_datagram_buf[MAX_DATAGRAM];
+       qbyte reliable_datagram_buf[NET_MAXMESSAGE];
 
        sizebuf_t signon;
-       // LordHavoc: increased signon message buffer from 8192 to 32768
-       qbyte signon_buf[32768];
+       // LordHavoc: increased signon message buffer from 8192
+       qbyte signon_buf[NET_MAXMESSAGE];
 } server_t;
 
 
@@ -127,7 +127,7 @@ typedef struct client_s
 
        // can be added to at any time, copied and clear once per frame
        sizebuf_t message;
-       qbyte msgbuf[MAX_DATAGRAM];
+       qbyte msgbuf[NET_MAXMESSAGE];
        // EDICT_NUM(clientnum+1)
        edict_t *edict;
 
index 9893dc3..d695f3b 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -1001,10 +1001,15 @@ void SV_WriteEntitiesToClient(client_t *client, edict_t *clent, sizebuf_t *msg)
        vec3_t testorigin;
        entity_state_t *s;
        entity_database4_t *d;
-       int maxbytes, n, startnumber;
+       int n, startnumber;
        entity_state_t *e, inactiveentitystate;
        sizebuf_t buf;
        qbyte data[128];
+
+       // if there isn't enough space to accomplish anything, skip it
+       if (msg->cursize + 24 > msg->maxsize)
+               return;
+
        // prepare the buffer
        memset(&buf, 0, sizeof(buf));
        buf.data = data;
@@ -1056,10 +1061,6 @@ void SV_WriteEntitiesToClient(client_t *client, edict_t *clent, sizebuf_t *msg)
        for (i = 0;i < numsendentities;i++)
                SV_MarkWriteEntityStateToClient(sendentities + i);
 
-       // calculate maximum bytes to allow in this packet
-       // deduct 4 to account for the end data
-       maxbytes = min(msg->maxsize, MAX_PACKETFRAGMENT) - 4;
-
        d->currentcommit->numentities = 0;
        d->currentcommit->framenum = ++client->entityframenumber;
        MSG_WriteByte(msg, svc_entities);
@@ -1117,7 +1118,7 @@ void SV_WriteEntitiesToClient(client_t *client, edict_t *clent, sizebuf_t *msg)
                        }
                }
                // if the commit is full, we're done this frame
-               if (msg->cursize + buf.cursize > maxbytes)
+               if (msg->cursize + buf.cursize > msg->maxsize - 4)
                {
                        // next frame we will continue where we left off
                        break;
@@ -1341,13 +1342,13 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
 SV_SendClientDatagram
 =======================
 */
-static qbyte sv_sendclientdatagram_buf[MAX_DATAGRAM]; // FIXME?
+static qbyte sv_sendclientdatagram_buf[NET_MAXMESSAGE]; // FIXME?
 qboolean SV_SendClientDatagram (client_t *client)
 {
        sizebuf_t       msg;
 
        msg.data = sv_sendclientdatagram_buf;
-       msg.maxsize = sizeof(sv_sendclientdatagram_buf);
+       msg.maxsize = (int)bound(50.0, client->netconnection->rate * host_realframetime, (double)sizeof(sv_sendclientdatagram_buf));
        msg.cursize = 0;
 
        MSG_WriteByte (&msg, svc_time);
@@ -1359,7 +1360,8 @@ qboolean SV_SendClientDatagram (client_t *client)
        SV_WriteEntitiesToClient (client, client->edict, &msg);
 
        // copy the server datagram if there is space
-       if (msg.cursize + sv.datagram.cursize < msg.maxsize)
+       // FIXME: put in delayed queue of effects to send
+       if (msg.cursize + sv.datagram.cursize <= msg.maxsize)
                SZ_Write (&msg, sv.datagram.data, sv.datagram.cursize);
 
 // send the datagram