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."};
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
}
}
-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];
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;
}
}
- // 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;
}
{
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;
}
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
{
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;
}
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;
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)
{
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));
{
crypto_t *crypto;
cls.connect_trying = false;
+#ifdef CONFIG_MENU
M_Update_Return_Reason("");
+#endif
// the connection request succeeded, stop current connection and set up a new connection
CL_Disconnect();
// if we're connecting to a remote server, shut down any local server
}
Con_Printf("Connection accepted to %s\n", cls.netcon->address);
key_dest = key_game;
+#ifdef CONFIG_MENU
m_state = m_none;
+#endif
cls.demonum = -1; // not in the demo loop now
cls.state = ca_connected;
cls.signon = 0; // need all the signon messages before playing
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);
}
}
char protocolnames[1400];
Protocol_Names(protocolnames, sizeof(protocolnames));
Con_DPrintf("\"%s\" received, sending connect request back to %s\n", string, addressstring2);
+#ifdef CONFIG_MENU
M_Update_Return_Reason("Got challenge response");
+#endif
// update the server IP in the userinfo (QW servers expect this, and it is used by the reconnect command)
InfoString_SetValue(cls.userinfo, sizeof(cls.userinfo), "*ip", addressstring2);
// TODO: add userinfo stuff here instead of using NQ commands?
if (length == 6 && !memcmp(string, "accept", 6) && cls.connect_trying)
{
// darkplaces or quake3
+#ifdef CONFIG_MENU
M_Update_Return_Reason("Accepted");
+#endif
NetConn_ConnectionEstablished(mysocket, peeraddress, PROTOCOL_DARKPLACES3);
return true;
}
length = min(length - 7, (int)sizeof(rejectreason) - 1);
memcpy(rejectreason, string, length);
rejectreason[length] = 0;
+#ifdef CONFIG_MENU
M_Update_Return_Reason(rejectreason);
+#endif
return true;
}
if (length >= 15 && !memcmp(string, "statusResponse\x0A", 15))
{
// challenge message
Con_Printf("challenge %s received, sending QuakeWorld connect request back to %s\n", string + 1, addressstring2);
+#ifdef CONFIG_MENU
M_Update_Return_Reason("Got QuakeWorld challenge response");
+#endif
cls.qw_qport = qport.integer;
// update the server IP in the userinfo (QW servers expect this, and it is used by the reconnect command)
InfoString_SetValue(cls.userinfo, sizeof(cls.userinfo), "*ip", addressstring2);
if (length >= 1 && string[0] == 'j' && cls.connect_trying)
{
// accept message
+#ifdef CONFIG_MENU
M_Update_Return_Reason("QuakeWorld Accepted");
+#endif
NetConn_ConnectionEstablished(mysocket, peeraddress, PROTOCOL_QUAKEWORLD);
return true;
}
Con_Printf("Connected to ProQuake %.1f server, enabling precise aim\n", cls.proquake_serverversion / 10.0f);
// update the server IP in the userinfo (QW servers expect this, and it is used by the reconnect command)
InfoString_SetValue(cls.userinfo, sizeof(cls.userinfo), "*ip", addressstring2);
+#ifdef CONFIG_MENU
M_Update_Return_Reason("Accepted");
+#endif
NetConn_ConnectionEstablished(mysocket, &clientportaddress, PROTOCOL_QUAKE);
}
break;
if (developer_extra.integer)
Con_DPrintf("Datagram_ParseConnectionless: received CCREP_REJECT from %s.\n", addressstring2);
cls.connect_trying = false;
+#ifdef CONFIG_MENU
M_Update_Return_Reason((char *)MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)));
+#endif
break;
case CCREP_SERVER_INFO:
if (developer_extra.integer)
NetConn_UpdateSockets();
if (cls.connect_trying && cls.connect_nextsendtime < realtime)
{
+#ifdef CONFIG_MENU
if (cls.connect_remainingtries == 0)
M_Update_Return_Reason("Connect: Waiting 10 seconds for reply");
+#endif
cls.connect_nextsendtime = realtime + 1;
cls.connect_remainingtries--;
if (cls.connect_remainingtries <= -10)
{
cls.connect_trying = false;
+#ifdef CONFIG_MENU
M_Update_Return_Reason("Connect: Failed");
+#endif
return;
}
// try challenge first (newer DP server or QW)
*p = 0;
}
- if ((gamemode == GAME_NEXUIZ || gamemode == GAME_XONOTIC) && (teamplay.integer > 0))
+ if (IS_NEXUIZ_DERIVED(gamemode) && (teamplay.integer > 0))
{
if(cl->frags == -666) // spectator
strlcpy(teambuf, " 0", sizeof(teambuf));
{
if (sv_qwmasters[masternum].string && LHNETADDRESS_FromString(&masteraddress, sv_qwmasters[masternum].string, QWMASTER_PORT) && LHNETADDRESS_GetAddressType(&masteraddress) == LHNETADDRESS_GetAddressType(LHNET_AddressFromSocket(cl_sockets[i])))
{
+#ifdef CONFIG_MENU
if (m_state != m_slist)
{
+#endif
char lookupstring[128];
LHNETADDRESS_ToString(&masteraddress, lookupstring, sizeof(lookupstring), true);
Con_Printf("Querying master %s (resolved from %s)\n", lookupstring, sv_qwmasters[masternum].string);
+#ifdef CONFIG_MENU
}
+#endif
masterquerycount++;
NetConn_Write(cl_sockets[i], request, (int)strlen(request) + 1, &masteraddress);
}
if (!masterquerycount)
{
Con_Print("Unable to query master servers, no suitable network sockets active.\n");
+#ifdef CONFIG_MENU
M_Update_Return_Reason("No network");
+#endif
}
}
void Net_Refresh_f(void)
{
+#ifdef CONFIG_MENU
if (m_state != m_slist) {
+#endif
Con_Print("Sending new requests to master servers\n");
ServerList_QueryList(false, true, false, true);
Con_Print("Listening for replies...\n");
+#ifdef CONFIG_MENU
} else
ServerList_QueryList(false, true, false, false);
+#endif
}
void Net_Slist_f(void)
ServerList_ResetMasks();
serverlist_sortbyfield = SLIF_PING;
serverlist_sortflags = 0;
+#ifdef CONFIG_MENU
if (m_state != m_slist) {
+#endif
Con_Print("Sending requests to master servers\n");
ServerList_QueryList(true, true, false, true);
Con_Print("Listening for replies...\n");
+#ifdef CONFIG_MENU
} else
ServerList_QueryList(true, true, false, false);
+#endif
}
void Net_SlistQW_f(void)
ServerList_ResetMasks();
serverlist_sortbyfield = SLIF_PING;
serverlist_sortflags = 0;
+#ifdef CONFIG_MENU
if (m_state != m_slist) {
+#endif
Con_Print("Sending requests to master servers\n");
ServerList_QueryList(true, false, true, true);
serverlist_consoleoutput = true;
Con_Print("Listening for replies...\n");
+#ifdef CONFIG_MENU
} else
ServerList_QueryList(true, false, true, false);
+#endif
}
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);