// 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++)
{
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();
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;
//
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;
}
}
+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
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);
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];
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");
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;
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;
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;
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++;
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;
#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
lhnetsocket_t *mysocket;
lhnetaddress_t peeraddress;
+
+ // requested rate in bytes per second
+ int rate;
// this is mostly identical to qsocket_t from quake
int receiveMessageLength;
qbyte receiveMessage[NET_MAXMESSAGE];
- char address[NET_NAMELEN];
+ char address[128];
} netconn_t;
extern netconn_t *netconn_list;
#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
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;
// 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;
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;
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);
}
}
// 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;
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);
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