#ifdef CONFIG_MENU
static cvar_t sv_qwmasters [] =
{
- {CF_CLIENT | CF_SERVER | CF_ARCHIVE, "sv_qwmaster1", "", "user-chosen qwmaster server 1"},
- {CF_CLIENT | CF_SERVER | CF_ARCHIVE, "sv_qwmaster2", "", "user-chosen qwmaster server 2"},
- {CF_CLIENT | CF_SERVER | CF_ARCHIVE, "sv_qwmaster3", "", "user-chosen qwmaster server 3"},
- {CF_CLIENT | CF_SERVER | CF_ARCHIVE, "sv_qwmaster4", "", "user-chosen qwmaster server 4"},
- {CF_CLIENT | CF_SERVER, "sv_qwmasterextra1", "master.quakeservers.net:27000", "Global master server. (admin: unknown)"},
- {CF_CLIENT | CF_SERVER, "sv_qwmasterextra2", "asgaard.morphos-team.net:27000", "Global master server. (admin: unknown)"},
- {CF_CLIENT | CF_SERVER, "sv_qwmasterextra3", "qwmaster.ocrana.de:27000", "German master server. (admin: unknown)"},
- {CF_CLIENT | CF_SERVER, "sv_qwmasterextra4", "qwmaster.fodquake.net:27000", "Global master server. (admin: unknown)"},
+ {CF_CLIENT | CF_ARCHIVE, "sv_qwmaster1", "", "user-chosen qwmaster server 1"},
+ {CF_CLIENT | CF_ARCHIVE, "sv_qwmaster2", "", "user-chosen qwmaster server 2"},
+ {CF_CLIENT | CF_ARCHIVE, "sv_qwmaster3", "", "user-chosen qwmaster server 3"},
+ {CF_CLIENT | CF_ARCHIVE, "sv_qwmaster4", "", "user-chosen qwmaster server 4"},
+ {CF_CLIENT, "sv_qwmasterextra1", "master.quakeservers.net:27000", "Global master server. (admin: unknown)"},
+ {CF_CLIENT, "sv_qwmasterextra2", "asgaard.morphos-team.net:27000", "Global master server. (admin: unknown)"},
+ {CF_CLIENT, "sv_qwmasterextra3", "qwmaster.ocrana.de:27000", "German master server. (admin: unknown)"},
+ {CF_CLIENT, "sv_qwmasterextra4", "qwmaster.fodquake.net:27000", "Global master server. (admin: unknown)"},
};
#endif
#ifdef CONFIG_MENU
static cvar_t net_slist_debug = {CF_CLIENT, "net_slist_debug", "0", "enables verbose messages for master server queries"};
static cvar_t net_slist_favorites = {CF_CLIENT | CF_ARCHIVE, "net_slist_favorites", "", "contains a list of IP addresses and ports to always query explicitly"};
-static cvar_t net_slist_interval = {CF_CLIENT, "net_slist_interval", "1.125", "minimum number of seconds to wait between getstatus queries to the same DP server, must be >= server's net_getstatusfloodblockingtimeout"};
+static cvar_t net_slist_interval = {CF_CLIENT, "net_slist_interval", "1", "minimum number of seconds to wait between getstatus queries to the same DP server, must be >= server's net_getstatusfloodblockingtimeout"};
static cvar_t net_slist_maxping = {CF_CLIENT | CF_ARCHIVE, "net_slist_maxping", "420", "server query responses are ignored if their ping in milliseconds is higher than this"};
static cvar_t net_slist_maxtries = {CF_CLIENT, "net_slist_maxtries", "3", "how many times to ask the same server for information (more times gives better ping reports but takes longer)"};
static cvar_t net_slist_pause = {CF_CLIENT, "net_slist_pause", "0", "when set to 1, the server list sorting in the menu won't update until it is set back to 0"};
// currently 44 bytes, longest possible IPv6 address: 39 bytes, so this works
// (if v6 address contains port, it must start with '[')
{
- strlcpy(favorites_idfp[nFavorites_idfp], com_token, sizeof(favorites_idfp[nFavorites_idfp]));
+ dp_strlcpy(favorites_idfp[nFavorites_idfp], com_token, sizeof(favorites_idfp[nFavorites_idfp]));
++nFavorites_idfp;
}
else
{
serverlist_entry_t *entry = &serverlist_cache[i];
entry->responded = false;
- entry->querycounter = 0;
}
}
serverlist_consoleoutput = consoleoutput;
conn->packetsReceived++;
reliable_message = (sequence >> 31) != 0;
reliable_ack = (sequence_ack >> 31) != 0;
- sequence &= ~(1<<31);
- sequence_ack &= ~(1<<31);
+ sequence &= ~(1u<<31);
+ sequence_ack &= ~(1u<<31);
if (sequence <= conn->qw.incoming_sequence)
{
//Con_DPrint("Got a stale datagram\n");
static void NetConn_ConnectionEstablished(lhnetsocket_t *mysocket, lhnetaddress_t *peeraddress, protocolversion_t initialprotocol)
{
crypto_t *crypto;
+
cls.connect_trying = false;
-#ifdef CONFIG_MENU
- M_Update_Return_Reason("");
-#endif
// Disconnect from the current server or stop demo playback
if(cls.state == ca_connected || cls.demoplayback)
CL_Disconnect();
// allocate a net connection to keep track of things
cls.netcon = NetConn_Open(mysocket, peeraddress);
+ dp_strlcpy(cl_connect_status, "Connection established", sizeof(cl_connect_status));
crypto = &cls.netcon->crypto;
if(cls.crypto.authenticated)
{
crypto_keyfp_recommended_length, crypto->client_keyfp[0] ? crypto->client_keyfp : "-"
);
}
- Con_Printf("Connection accepted to %s\n", cls.netcon->address);
+ else
+ Con_Printf("%s to %s\n", cl_connect_status, cls.netcon->address);
+
key_dest = key_game;
#ifdef CONFIG_MENU
m_state = m_none;
entry = &serverlist_cache[n];
memset(entry, 0, sizeof(*entry));
- strlcpy(entry->info.cname, addressstring, sizeof(entry->info.cname));
+ entry->info.cname_len = dp_strlcpy(entry->info.cname, addressstring, sizeof(entry->info.cname));
- // consider the broadcast to be the first query
- // NetConn_QueryQueueFrame() will perform more until net_slist_maxtries is reached
- entry->querycounter = 1;
+ // use the broadcast as the first query, NetConn_QueryQueueFrame() will send more
entry->querytime = masterquerytime;
// protocol is one of these at all
// NetConn_ClientParsePacket_ServerList_PrepareQuery() callsites
serverlist_info_t *info = &entry->info;
// update description strings for engine menu and console output
- dpsnprintf(entry->line1, sizeof(serverlist_cache[n].line1), "^%c%5.0f^7 ^%c%3u^7/%3u %-65.65s",
+ entry->line1_len = dpsnprintf(entry->line1, sizeof(serverlist_cache[n].line1), "^%c%5.0f^7 ^%c%3u^7/%3u %-65.65s",
info->ping >= 300 ? '1' : (info->ping >= 200 ? '3' : '7'),
info->ping ?: INFINITY, // display inf when a listed server times out and net_slist_pause blocks its removal
((info->numhumans > 0 && info->numhumans < info->maxplayers) ? (info->numhumans >= 4 ? '7' : '3') : '1'),
info->numplayers,
info->maxplayers,
info->name);
- dpsnprintf(entry->line2, sizeof(serverlist_cache[n].line2), "^4%-21.21s %-19.19s ^%c%-17.17s^4 %-20.20s", info->cname, info->game,
+ entry->line2_len = dpsnprintf(entry->line2, sizeof(serverlist_cache[n].line2), "^4%-21.21s %-19.19s ^%c%-17.17s^4 %-20.20s", info->cname, info->game,
(
info->gameversion != gameversion.integer
&&
entry = &serverlist_cache[n];
memset(entry, 0, sizeof(*entry));
entry->protocol = protocol;
- strlcpy(entry->info.cname, ipstring, sizeof(entry->info.cname));
+ entry->info.cname_len = dp_strlcpy(entry->info.cname, ipstring, sizeof(entry->info.cname));
entry->info.isfavorite = isfavorite;
serverlist_cachecount++;
size_t sendlength;
#ifdef CONFIG_MENU
char infostringvalue[MAX_INPUTLINE];
- const char *s;
#endif
// quakeworld ingame packet
}
sendlength = sizeof(senddata) - 4;
- switch(Crypto_ClientParsePacket(string, length, senddata+4, &sendlength, peeraddress))
+ switch(Crypto_ClientParsePacket(string, length, senddata+4, &sendlength, peeraddress, addressstring2))
{
case CRYPTO_NOMATCH:
// nothing to do
{
int k;
buf[45] = ' ';
- strlcpy(buf + 46, argbuf, sizeof(buf) - 46);
+ dp_strlcpy(buf + 46, argbuf, sizeof(buf) - 46);
NetConn_Write(mysocket, buf, 46 + (int)strlen(buf + 46), peeraddress);
cls.rcon_commands[i][0] = 0;
--cls.rcon_trying;
{
// darkplaces or quake3
char protocolnames[1400];
- Con_DPrintf("\"%s\" received, sending connect request back to %s\n", string, addressstring2);
+
if (net_sourceaddresscheck.integer && LHNETADDRESS_Compare(peeraddress, &cls.connect_address)) {
- Con_DPrintf("challenge message from wrong server %s\n", addressstring2);
+ Con_Printf(CON_WARN "ignoring challenge message from wrong server %s\n", addressstring2);
return true;
}
+ Con_DPrintf("\"%s\" received, sending connect request back to %s\n", string, addressstring2);
+ dp_strlcpy(cl_connect_status, "Connect: replying to challenge...", sizeof(cl_connect_status));
+
Protocol_Names(protocolnames, sizeof(protocolnames));
-#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?
{
// darkplaces or quake3
if (net_sourceaddresscheck.integer && LHNETADDRESS_Compare(peeraddress, &cls.connect_address)) {
- Con_DPrintf("accept message from wrong server %s\n", addressstring2);
+ Con_Printf(CON_WARN "ignoring accept message from wrong server %s\n", addressstring2);
return true;
}
-#ifdef CONFIG_MENU
- M_Update_Return_Reason("Accepted");
-#endif
NetConn_ConnectionEstablished(mysocket, peeraddress, PROTOCOL_DARKPLACES3);
return true;
}
if (length > 7 && !memcmp(string, "reject ", 7) && cls.connect_trying)
{
- char rejectreason[128];
if (net_sourceaddresscheck.integer && LHNETADDRESS_Compare(peeraddress, &cls.connect_address)) {
- Con_DPrintf("reject message from wrong server %s\n", addressstring2);
+ Con_Printf(CON_WARN "ignoring reject message from wrong server %s\n", addressstring2);
return true;
}
cls.connect_trying = false;
string += 7;
- length = min(length - 7, (int)sizeof(rejectreason) - 1);
- memcpy(rejectreason, string, length);
- rejectreason[length] = 0;
-#ifdef CONFIG_MENU
- M_Update_Return_Reason(rejectreason);
-#endif
+ length = min(length - 7, (int)sizeof(cl_connect_status) - 1);
+ dpsnprintf(cl_connect_status, sizeof(cl_connect_status), "Connect: rejected, %.*s", length, string);
+ Con_Printf(CON_ERROR "Connect: rejected by %s\n" CON_ERROR "%.*s\n", addressstring2, length, string);
return true;
}
#ifdef CONFIG_MENU
string += 15;
// search the cache for this server and update it
// the challenge is (ab)used to return the query time
- s = InfoString_GetValue(string, "challenge", infostringvalue, sizeof(infostringvalue));
- n = NetConn_ClientParsePacket_ServerList_ProcessReply(addressstring2, s);
+ InfoString_GetValue(string, "challenge", infostringvalue, sizeof(infostringvalue));
+ n = NetConn_ClientParsePacket_ServerList_ProcessReply(addressstring2, infostringvalue);
if (n < 0)
return true;
info = &serverlist_cache[n].info;
- info->game[0] = 0;
- info->mod[0] = 0;
- info->map[0] = 0;
- info->name[0] = 0;
- info->qcstatus[0] = 0;
- info->players[0] = 0;
- info->protocol = -1;
- info->numplayers = 0;
- info->numbots = -1;
- info->maxplayers = 0;
- info->gameversion = 0;
-
p = strchr(string, '\n');
if(p)
{
*p = 0; // cut off the string there
++p;
+ info->players_len = dp_strlcpy(info->players, p, sizeof(info->players));
}
else
+ {
Con_Printf("statusResponse without players block?\n");
-
- if ((s = InfoString_GetValue(string, "gamename" , infostringvalue, sizeof(infostringvalue))) != NULL) strlcpy(info->game, s, sizeof (info->game));
- if ((s = InfoString_GetValue(string, "modname" , infostringvalue, sizeof(infostringvalue))) != NULL) strlcpy(info->mod , s, sizeof (info->mod ));
- if ((s = InfoString_GetValue(string, "mapname" , infostringvalue, sizeof(infostringvalue))) != NULL) strlcpy(info->map , s, sizeof (info->map ));
- if ((s = InfoString_GetValue(string, "hostname" , infostringvalue, sizeof(infostringvalue))) != NULL) strlcpy(info->name, s, sizeof (info->name));
- if ((s = InfoString_GetValue(string, "protocol" , infostringvalue, sizeof(infostringvalue))) != NULL) info->protocol = atoi(s);
- if ((s = InfoString_GetValue(string, "clients" , infostringvalue, sizeof(infostringvalue))) != NULL) info->numplayers = atoi(s);
- if ((s = InfoString_GetValue(string, "bots" , infostringvalue, sizeof(infostringvalue))) != NULL) info->numbots = atoi(s);
- if ((s = InfoString_GetValue(string, "sv_maxclients", infostringvalue, sizeof(infostringvalue))) != NULL) info->maxplayers = atoi(s);
- if ((s = InfoString_GetValue(string, "gameversion" , infostringvalue, sizeof(infostringvalue))) != NULL) info->gameversion = atoi(s);
- if ((s = InfoString_GetValue(string, "qcstatus" , infostringvalue, sizeof(infostringvalue))) != NULL) strlcpy(info->qcstatus, s, sizeof(info->qcstatus));
- if (p != NULL) strlcpy(info->players, p, sizeof(info->players));
+ info->players_len = info->players[0] = 0;
+ }
+ info->game_len = InfoString_GetValue(string, "gamename", info->game, sizeof(info->game));
+ info->mod_len = InfoString_GetValue(string, "modname", info->mod, sizeof(info->mod));
+ info->map_len = InfoString_GetValue(string, "mapname", info->map, sizeof(info->map));
+ info->name_len = InfoString_GetValue(string, "hostname", info->name, sizeof(info->name));
+ info->qcstatus_len = InfoString_GetValue(string, "qcstatus", info->qcstatus, sizeof(info->qcstatus));
+ info->protocol = InfoString_GetValue(string, "protocol" , infostringvalue, sizeof(infostringvalue)) ? atoi(infostringvalue) : -1;
+ info->numplayers = InfoString_GetValue(string, "clients" , infostringvalue, sizeof(infostringvalue)) ? atoi(infostringvalue) : 0;
+ info->numbots = InfoString_GetValue(string, "bots" , infostringvalue, sizeof(infostringvalue)) ? atoi(infostringvalue) : -1;
+ info->maxplayers = InfoString_GetValue(string, "sv_maxclients", infostringvalue, sizeof(infostringvalue)) ? atoi(infostringvalue) : 0;
+ info->gameversion = InfoString_GetValue(string, "gameversion" , infostringvalue, sizeof(infostringvalue)) ? atoi(infostringvalue) : 0;
info->numhumans = info->numplayers - max(0, info->numbots);
info->freeslots = info->maxplayers - info->numplayers;
string += 13;
// search the cache for this server and update it
// the challenge is (ab)used to return the query time
- s = InfoString_GetValue(string, "challenge", infostringvalue, sizeof(infostringvalue));
- n = NetConn_ClientParsePacket_ServerList_ProcessReply(addressstring2, s);
+ InfoString_GetValue(string, "challenge", infostringvalue, sizeof(infostringvalue));
+ n = NetConn_ClientParsePacket_ServerList_ProcessReply(addressstring2, infostringvalue);
if (n < 0)
return true;
info = &serverlist_cache[n].info;
- info->game[0] = 0;
- info->mod[0] = 0;
- info->map[0] = 0;
- info->name[0] = 0;
- info->qcstatus[0] = 0;
- info->players[0] = 0;
- info->protocol = -1;
- info->numplayers = 0;
- info->numbots = -1;
- info->maxplayers = 0;
- info->gameversion = 0;
-
- if ((s = InfoString_GetValue(string, "gamename" , infostringvalue, sizeof(infostringvalue))) != NULL) strlcpy(info->game, s, sizeof (info->game));
- if ((s = InfoString_GetValue(string, "modname" , infostringvalue, sizeof(infostringvalue))) != NULL) strlcpy(info->mod , s, sizeof (info->mod ));
- if ((s = InfoString_GetValue(string, "mapname" , infostringvalue, sizeof(infostringvalue))) != NULL) strlcpy(info->map , s, sizeof (info->map ));
- if ((s = InfoString_GetValue(string, "hostname" , infostringvalue, sizeof(infostringvalue))) != NULL) strlcpy(info->name, s, sizeof (info->name));
- if ((s = InfoString_GetValue(string, "protocol" , infostringvalue, sizeof(infostringvalue))) != NULL) info->protocol = atoi(s);
- if ((s = InfoString_GetValue(string, "clients" , infostringvalue, sizeof(infostringvalue))) != NULL) info->numplayers = atoi(s);
- if ((s = InfoString_GetValue(string, "bots" , infostringvalue, sizeof(infostringvalue))) != NULL) info->numbots = atoi(s);
- if ((s = InfoString_GetValue(string, "sv_maxclients", infostringvalue, sizeof(infostringvalue))) != NULL) info->maxplayers = atoi(s);
- if ((s = InfoString_GetValue(string, "gameversion" , infostringvalue, sizeof(infostringvalue))) != NULL) info->gameversion = atoi(s);
- if ((s = InfoString_GetValue(string, "qcstatus" , infostringvalue, sizeof(infostringvalue))) != NULL) strlcpy(info->qcstatus, s, sizeof(info->qcstatus));
+ info->players_len = info->players[0] = 0;
+ info->game_len = InfoString_GetValue(string, "gamename", info->game, sizeof(info->game));
+ info->mod_len = InfoString_GetValue(string, "modname", info->mod, sizeof(info->mod));
+ info->map_len = InfoString_GetValue(string, "mapname", info->map, sizeof(info->map));
+ info->name_len = InfoString_GetValue(string, "hostname", info->name, sizeof(info->name));
+ info->qcstatus_len = InfoString_GetValue(string, "qcstatus", info->qcstatus, sizeof(info->qcstatus));
+ info->protocol = InfoString_GetValue(string, "protocol" , infostringvalue, sizeof(infostringvalue)) ? atoi(infostringvalue) : -1;
+ info->numplayers = InfoString_GetValue(string, "clients" , infostringvalue, sizeof(infostringvalue)) ? atoi(infostringvalue) : 0;
+ info->numbots = InfoString_GetValue(string, "bots" , infostringvalue, sizeof(infostringvalue)) ? atoi(infostringvalue) : -1;
+ info->maxplayers = InfoString_GetValue(string, "sv_maxclients", infostringvalue, sizeof(infostringvalue)) ? atoi(infostringvalue) : 0;
+ info->gameversion = InfoString_GetValue(string, "gameversion" , infostringvalue, sizeof(infostringvalue)) ? atoi(infostringvalue) : 0;
info->numhumans = info->numplayers - max(0, info->numbots);
info->freeslots = info->maxplayers - info->numplayers;
{
// challenge message
if (net_sourceaddresscheck.integer && LHNETADDRESS_Compare(peeraddress, &cls.connect_address)) {
- Con_DPrintf("c message from wrong server %s\n", addressstring2);
+ Con_Printf(CON_WARN "ignoring c message from wrong server %s\n", addressstring2);
return true;
}
- 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
+ Con_DPrintf("challenge %s received, sending QuakeWorld connect request back to %s\n", string + 1, addressstring2);
+ dp_strlcpy(cl_connect_status, "Connect: replying to challenge...", sizeof(cl_connect_status));
+
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);
{
// accept message
if (net_sourceaddresscheck.integer && LHNETADDRESS_Compare(peeraddress, &cls.connect_address)) {
- Con_DPrintf("j message from wrong server %s\n", addressstring2);
+ Con_Printf(CON_WARN "ignoring j message from wrong server %s\n", addressstring2);
return true;
}
-#ifdef CONFIG_MENU
- M_Update_Return_Reason("QuakeWorld Accepted");
-#endif
NetConn_ConnectionEstablished(mysocket, peeraddress, PROTOCOL_QUAKEWORLD);
return true;
}
#ifdef CONFIG_MENU
serverlist_info_t *info;
int n;
+ const char *s;
// qw server status
if (serverlist_consoleoutput && developer_networking.integer >= 2)
return true;
info = &serverlist_cache[n].info;
- strlcpy(info->game, "QuakeWorld", sizeof(info->game));
- if ((s = InfoString_GetValue(string, "*gamedir" , infostringvalue, sizeof(infostringvalue))) != NULL) strlcpy(info->mod , s, sizeof (info->mod ));else info->mod[0] = 0;
- if ((s = InfoString_GetValue(string, "map" , infostringvalue, sizeof(infostringvalue))) != NULL) strlcpy(info->map , s, sizeof (info->map ));else info->map[0] = 0;
- if ((s = InfoString_GetValue(string, "hostname" , infostringvalue, sizeof(infostringvalue))) != NULL) strlcpy(info->name, s, sizeof (info->name));else info->name[0] = 0;
+ dp_strlcpy(info->game, "QuakeWorld", sizeof(info->game));
+ info->mod_len = InfoString_GetValue(string, "*gamedir", info->mod, sizeof(info->mod));
+ info->map_len = InfoString_GetValue(string, "map" , info->map, sizeof(info->map));
+ info->name_len = InfoString_GetValue(string, "hostname", info->name, sizeof(info->name));
info->protocol = 0;
info->numplayers = 0; // updated below
info->numhumans = 0; // updated below
- if ((s = InfoString_GetValue(string, "maxclients" , infostringvalue, sizeof(infostringvalue))) != NULL) info->maxplayers = atoi(s);else info->maxplayers = 0;
- if ((s = InfoString_GetValue(string, "gameversion" , infostringvalue, sizeof(infostringvalue))) != NULL) info->gameversion = atoi(s);else info->gameversion = 0;
+ info->maxplayers = InfoString_GetValue(string, "maxclients" , infostringvalue, sizeof(infostringvalue)) ? atoi(infostringvalue) : 0;
+ info->gameversion = InfoString_GetValue(string, "gameversion", infostringvalue, sizeof(infostringvalue)) ? atoi(infostringvalue) : 0;
// count active players on server
// (we could gather more info, but we're just after the number)
{
// qw print command, used by rcon replies too
if (net_sourceaddresscheck.integer && LHNETADDRESS_Compare(peeraddress, &cls.connect_address) && LHNETADDRESS_Compare(peeraddress, &cls.rcon_address)) {
- Con_DPrintf("n message from wrong server %s\n", addressstring2);
+ Con_Printf(CON_WARN "ignoring n message from wrong server %s\n", addressstring2);
return true;
}
Con_Printf("QW print command from server at %s:\n%s\n", addressstring2, string + 1);
{
lhnetaddress_t clientportaddress;
if (net_sourceaddresscheck.integer && LHNETADDRESS_Compare(peeraddress, &cls.connect_address)) {
- Con_DPrintf("CCREP_ACCEPT message from wrong server %s\n", addressstring2);
+ Con_Printf(CON_WARN "ignoring CCREP_ACCEPT message from wrong server %s\n", addressstring2);
break;
}
clientportaddress = *peeraddress;
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;
case CCREP_REJECT:
- if (developer_extra.integer) {
- Con_DPrintf("CCREP_REJECT message from wrong server %s\n", addressstring2);
- break;
- }
if (net_sourceaddresscheck.integer && LHNETADDRESS_Compare(peeraddress, &cls.connect_address))
+ {
+ Con_Printf(CON_WARN "ignoring CCREP_REJECT message from wrong server %s\n", addressstring2);
break;
+ }
cls.connect_trying = false;
-#ifdef CONFIG_MENU
- M_Update_Return_Reason((char *)MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)));
-#endif
+ dpsnprintf(cl_connect_status, sizeof(cl_connect_status), "Connect: rejected, %s", MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)));
+ Con_Printf(CON_ERROR "Connect: rejected by %s\n%s\n", addressstring2, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)));
break;
case CCREP_SERVER_INFO:
if (developer_extra.integer)
break;
info = &serverlist_cache[n].info;
- strlcpy(info->game, "Quake", sizeof(info->game));
- strlcpy(info->mod , "", sizeof(info->mod)); // mod name is not specified
- strlcpy(info->name, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof(info->name));
- strlcpy(info->map , MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof(info->map));
+ info->game_len = dp_strlcpy(info->game, "Quake", sizeof(info->game));
+ info->mod_len = dp_strlcpy(info->mod, "", sizeof(info->mod)); // mod name is not specified
+ info->name_len = dp_strlcpy(info->name, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof(info->name));
+ info->map_len = dp_strlcpy(info->map, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof(info->map));
info->numplayers = MSG_ReadByte(&cl_message);
info->maxplayers = MSG_ReadByte(&cl_message);
info->protocol = MSG_ReadByte(&cl_message);
break;
case CCREP_RCON: // RocketGuy: ProQuake rcon support
if (net_sourceaddresscheck.integer && LHNETADDRESS_Compare(peeraddress, &cls.rcon_address)) {
- Con_DPrintf("CCREP_RCON message from wrong server %s\n", addressstring2);
+ Con_Printf(CON_WARN "ignoring CCREP_RCON message from wrong server %s\n", addressstring2);
break;
}
if (developer_extra.integer)
void NetConn_QueryQueueFrame(void)
{
unsigned index;
- unsigned queries, maxqueries;
+ unsigned maxqueries;
char dpquery[53]; // theoretical max: 14+22+16+1
double currentrealtime;
static double querycounter = 0;
- qbool pending = false;
+ static unsigned pass = 0, server = 0;
+ unsigned queriesperserver = bound(1, net_slist_maxtries.integer, 8);
if (!serverlist_querystage)
return;
if (maxqueries == 0)
return;
- // QW depends on waiting "long enough" between queries that responses "definitely" refer to the most recent querytime
- // DP servers can echo back a timestamp for reliable (and more frequent, see net_slist_interval) pings
- ServerList_BuildDPServerQuery(dpquery, sizeof(dpquery), currentrealtime);
-
- for (index = 0, queries = 0; index < serverlist_cachecount && queries < maxqueries; ++index)
+ if (pass < queriesperserver)
{
- serverlist_entry_t *entry = &serverlist_cache[index];
+ // QW depends on waiting "long enough" between queries that responses "definitely" refer to the most recent querytime
+ // DP servers can echo back a timestamp for reliable (and more frequent, see net_slist_interval) pings
+ ServerList_BuildDPServerQuery(dpquery, sizeof(dpquery), currentrealtime);
- if (entry->querycounter < min(8, (unsigned)net_slist_maxtries.integer))
+ for (unsigned queries = 0; server < serverlist_cachecount; ++server)
{
lhnetaddress_t address;
unsigned socket;
+ serverlist_entry_t *entry = &serverlist_cache[server];
- // only check this when there are tries remaining so we finish querying sooner
- if (currentrealtime < entry->querytime + (entry->protocol == PROTOCOL_QUAKEWORLD ? net_slist_timeout : net_slist_interval).value)
- {
- pending = true;
- continue;
- }
+ if (queries >= maxqueries
+ || currentrealtime <= entry->querytime + (entry->protocol == PROTOCOL_QUAKEWORLD ? net_slist_timeout : net_slist_interval).value)
+ return; // continue this pass at the current server on a later frame
LHNETADDRESS_FromString(&address, entry->info.cname, 0);
if (entry->protocol == PROTOCOL_QUAKEWORLD)
}
entry->querytime = currentrealtime;
- entry->querycounter++;
queries++;
if (serverlist_consoleoutput)
- Con_Printf("querying %25s (%i. try)\n", entry->info.cname, entry->querycounter);
+ Con_Printf("querying %25s (%i. try)\n", entry->info.cname, pass + 1);
}
- else // reached net_slist_maxtries
- if (!entry->responded // no acceptable response during this refresh cycle
- && (entry->info.ping)) // visible in the list (has old ping from previous refresh cycle)
+ }
+ else
+ {
+ // check timeouts
+ for (; server < serverlist_cachecount; ++server)
{
- if (currentrealtime >= entry->querytime + net_slist_maxping.integer/1000)
+ serverlist_entry_t *entry = &serverlist_cache[server];
+
+ if (!entry->responded // no acceptable response during this refresh cycle
+ && entry->info.ping) // visible in the list (has old ping from previous refresh cycle)
{
- // you have no chance to survive make your timeout
- serverreplycount--;
- if(!net_slist_pause.integer)
- ServerList_ViewList_Remove(entry);
- entry->info.ping = 0; // removed later if net_slist_pause
+ if (currentrealtime > entry->querytime + net_slist_maxping.integer/1000)
+ {
+ // you have no chance to survive make your timeout
+ serverreplycount--;
+ if(!net_slist_pause.integer)
+ ServerList_ViewList_Remove(entry);
+ entry->info.ping = 0; // removed later if net_slist_pause
+ }
+ else // still has time
+ return; // continue this pass at the current server on a later frame
}
- else // still has time
- pending = true;
}
}
- // If we got to the end of the list (didn't hit maxqueries)
- // and no servers remain to be queried or checked for timeout,
- // there's nothing else to do here until the next refresh cycle.
- if (index >= serverlist_cachecount && !pending)
+ // We finished the pass, ie didn't stop at maxqueries
+ // or a server that can't be (re)queried or timed out yet.
+ ++pass;
+ server = 0;
+
+ if (pass == queriesperserver)
{
+ // timeout pass begins next frame
if (net_slist_debug.integer)
Con_Printf("^2Finished querying masters and servers in %f\n", currentrealtime - masterquerytime);
+ }
+ else if (pass > queriesperserver)
+ {
+ // Nothing else to do until the next refresh cycle.
+ if (net_slist_debug.integer)
+ Con_Printf("^4Finished checking server timeouts in %f\n", currentrealtime - serverlist_cache[serverlist_cachecount - 1].querytime);
serverlist_querystage = 0;
+ pass = 0;
}
}
#endif
unsigned char readbuffer[NET_HEADERSIZE+NET_MAXMESSAGE];
NetConn_UpdateSockets();
+
if (cls.connect_trying && cls.connect_nextsendtime < host.realtime)
{
-#ifdef CONFIG_MENU
- if (cls.connect_remainingtries == 0)
- M_Update_Return_Reason("Connect: Waiting 10 seconds for reply");
-#endif
- cls.connect_nextsendtime = host.realtime + 1;
- cls.connect_remainingtries--;
- if (cls.connect_remainingtries <= -10)
+ if (cls.connect_remainingtries > 0)
+ {
+ cls.connect_remainingtries--;
+ dpsnprintf(cl_connect_status, sizeof(cl_connect_status), "Connect: sending initial request, %i %s left...", cls.connect_remainingtries, cls.connect_remainingtries == 1 ? "retry" : "retries");
+ }
+ else
{
+ char address[128];
+
cls.connect_trying = false;
-#ifdef CONFIG_MENU
- M_Update_Return_Reason("Connect: Failed");
-#endif
+ LHNETADDRESS_ToString(&cls.connect_address, address, sizeof(address), true);
+ dp_strlcpy(cl_connect_status, "Connect: failed, no reply", sizeof(cl_connect_status));
+ Con_Printf(CON_ERROR "%s from %s\n", cl_connect_status, address);
return;
}
+ cls.connect_nextsendtime = host.realtime + 1;
+
// try challenge first (newer DP server or QW)
NetConn_WriteString(cls.connect_mysocket, "\377\377\377\377getchallenge", &cls.connect_address);
// then try netquake as a fallback (old server, or netquake)
NetConn_Write(cls.connect_mysocket, cl_message.data, cl_message.cursize, &cls.connect_address);
SZ_Clear(&cl_message);
}
+
for (i = 0;i < cl_numsockets;i++)
{
while (cl_sockets[i] && (length = NetConn_Read(cl_sockets[i], readbuffer, sizeof(readbuffer), &peeraddress)) > 0)
if (IS_NEXUIZ_DERIVED(gamemode) && (teamplay.integer > 0))
{
if(client->frags == -666) // spectator
- strlcpy(teambuf, " 0", sizeof(teambuf));
+ dp_strlcpy(teambuf, " 0", sizeof(teambuf));
else if(client->colors == 0x44) // red team
- strlcpy(teambuf, " 1", sizeof(teambuf));
+ dp_strlcpy(teambuf, " 1", sizeof(teambuf));
else if(client->colors == 0xDD) // blue team
- strlcpy(teambuf, " 2", sizeof(teambuf));
+ dp_strlcpy(teambuf, " 2", sizeof(teambuf));
else if(client->colors == 0xCC) // yellow team
- strlcpy(teambuf, " 3", sizeof(teambuf));
+ dp_strlcpy(teambuf, " 3", sizeof(teambuf));
else if(client->colors == 0x99) // pink team
- strlcpy(teambuf, " 4", sizeof(teambuf));
+ dp_strlcpy(teambuf, " 4", sizeof(teambuf));
else
- strlcpy(teambuf, " 0", sizeof(teambuf));
+ dp_strlcpy(teambuf, " 0", sizeof(teambuf));
}
else
*teambuf = 0;
while((userpass_end = strchr(userpass_start, ' ')))
{
have_usernames = true;
- strlcpy(buf, userpass_start, ((size_t)(userpass_end-userpass_start) >= sizeof(buf)) ? (int)(sizeof(buf)) : (int)(userpass_end-userpass_start+1));
+ dp_strlcpy(buf, userpass_start, ((size_t)(userpass_end-userpass_start) >= sizeof(buf)) ? (int)(sizeof(buf)) : (int)(userpass_end-userpass_start+1));
if(buf[0]) // Ignore empty entries due to leading/duplicate space.
if(comparator(peeraddress, buf, password, cs, cslen))
goto allow;
while((userpass_end = strchr(userpass_start, ' ')))
{
have_usernames = true;
- strlcpy(buf, userpass_start, ((size_t)(userpass_end-userpass_start) >= sizeof(buf)) ? (int)(sizeof(buf)) : (int)(userpass_end-userpass_start+1));
+ dp_strlcpy(buf, userpass_start, ((size_t)(userpass_end-userpass_start) >= sizeof(buf)) ? (int)(sizeof(buf)) : (int)(userpass_end-userpass_start+1));
if(buf[0]) // Ignore empty entries due to leading/duplicate space.
if(comparator(peeraddress, buf, password, cs, cslen))
goto check;
if(l)
{
client_t *host_client_save = host_client;
- Cmd_ExecuteString(cmd_local, s, src_local, true);
+ //Cmd_ExecuteString(cmd_local, s, src_local, true); // no variable expansion
+ // bones_was_here: prepending allows a loop such as `alias foo "bar; wait; foo"; foo`
+ // to be broken with an alias or unalias command
+ Cbuf_InsertText(cmd_local, s);
host_client = host_client_save;
// in case it is a command that changes host_client (like restart)
}
}
if (length > 8 && !memcmp(string, "connect\\", 8))
{
- char *s;
client_t *client;
crypto_t *crypto = Crypto_ServerGetInstance(peeraddress);
string += 7;
}
else
{
- if ((s = InfoString_GetValue(string, "challenge", infostringvalue, sizeof(infostringvalue))))
+ if (InfoString_GetValue(string, "challenge", infostringvalue, sizeof(infostringvalue)))
{
// validate the challenge
for (i = 0;i < MAX_CHALLENGES;i++)
if(challenges[i].time > 0)
- if (!LHNETADDRESS_Compare(peeraddress, &challenges[i].address) && !strcmp(challenges[i].string, s))
+ if (!LHNETADDRESS_Compare(peeraddress, &challenges[i].address) && !strcmp(challenges[i].string, infostringvalue))
break;
// if the challenge is not recognized, drop the packet
if (i == MAX_CHALLENGES)
}
}
- if((s = InfoString_GetValue(string, "message", infostringvalue, sizeof(infostringvalue))))
- Con_DPrintf("Connecting client %s sent us the message: %s\n", addressstring2, s);
+ if(InfoString_GetValue(string, "message", infostringvalue, sizeof(infostringvalue)))
+ Con_DPrintf("Connecting client %s sent us the message: %s\n", addressstring2, infostringvalue);
if(!(islocal || sv_public.integer > -2))
{
}
// check engine protocol
- if(!(s = InfoString_GetValue(string, "protocol", infostringvalue, sizeof(infostringvalue))) || strcmp(s, "darkplaces 3"))
+ if(!InfoString_GetValue(string, "protocol", infostringvalue, sizeof(infostringvalue)) || strcmp(infostringvalue, "darkplaces 3"))
{
if (developer_extra.integer)
Con_Printf("Datagram_ParseConnectionless: sending \"reject Wrong game protocol.\" to %s.\n", addressstring2);
{
// connect to the client
// everything is allocated, just fill in the details
- strlcpy (conn->address, addressstring2, sizeof (conn->address));
+ dp_strlcpy (conn->address, addressstring2, sizeof (conn->address));
if (developer_extra.integer)
Con_DPrintf("Datagram_ParseConnectionless: sending CCREP_ACCEPT to %s.\n", addressstring2);
// send back the info about the server connection
char *s;
char *endpos;
const char *userlevel;
- strlcpy(password, MSG_ReadString(&sv_message, sv_readstring, sizeof(sv_readstring)), sizeof(password));
- strlcpy(cmd, MSG_ReadString(&sv_message, sv_readstring, sizeof(sv_readstring)), sizeof(cmd));
+ dp_strlcpy(password, MSG_ReadString(&sv_message, sv_readstring, sizeof(sv_readstring)), sizeof(password));
+ dp_strlcpy(cmd, MSG_ReadString(&sv_message, sv_readstring, sizeof(sv_readstring)), sizeof(cmd));
s = cmd;
endpos = cmd + strlen(cmd) + 1; // one behind the NUL, so adding strlen+1 will eventually reach it
userlevel = RCon_Authenticate(peeraddress, password, s, endpos, plaintext_matching, NULL, 0);
if (!masterquerycount)
{
Con_Print(CON_ERROR "Unable to query master servers, no suitable network sockets active.\n");
- M_Update_Return_Reason("No network");
+ dp_strlcpy(cl_connect_status, "No network", sizeof(cl_connect_status));
}
}
#endif
void NetConn_Init(void)
{
int i;
+ unsigned j;
lhnetaddress_t tempaddress;
+
netconn_mempool = Mem_AllocPool("network connections", 0, NULL);
Cmd_AddCommand(CF_SHARED, "net_stats", Net_Stats_f, "print network statistics");
#ifdef CONFIG_MENU
Cvar_RegisterVariable(&sv_public);
Cvar_RegisterVariable(&sv_public_rejectreason);
Cvar_RegisterVariable(&sv_heartbeatperiod);
- for (uint8_t masternum = 0; masternum < DPMASTER_COUNT; ++masternum)
- Cvar_RegisterVariable(&sv_masters[masternum]);
+ for (j = 0; j < DPMASTER_COUNT; ++j)
+ Cvar_RegisterVariable(&sv_masters[j]);
+#ifdef CONFIG_MENU
+ for (j = 0; j < QWMASTER_COUNT; ++j)
+ Cvar_RegisterVariable(&sv_qwmasters[j]);
+#endif
Cvar_RegisterVariable(&gameversion);
Cvar_RegisterVariable(&gameversion_min);
Cvar_RegisterVariable(&gameversion_max);