32#define QWMASTER_PORT 27000
33#define DPMASTER_PORT 27950
36cvar_t sv_public = {
CF_SERVER,
"sv_public",
"0",
"1: advertises this server on the master server (so that players can find it in the server browser); 0: allow direct queries only; -1: do not respond to direct queries; -2: do not allow anyone to connect; -3: already block at getchallenge level"};
47 {
CF_CLIENT |
CF_SERVER,
"sv_masterextra1",
"dpmaster.deathmask.net",
"dpmaster.deathmask.net - default master server 1 (admin: Willis)"},
48 {
CF_CLIENT |
CF_SERVER,
"sv_masterextra2",
"dpmaster.tchr.no",
"dpmaster.tchr.no - default master server 2 (admin: tChr)"},
49 {
CF_CLIENT |
CF_SERVER,
"sv_masterextra3",
"dpm.dpmaster.org:27777",
"dpm.dpmaster.org - default master server 3 (admin: gazby/soylent_cow)"},
57static cvar_t sv_qwmasters [] =
63 {
CF_CLIENT,
"sv_qwmasterextra1",
"master.quakeservers.net:27000",
"QW master in Germany, admin: unknown"},
64 {
CF_CLIENT,
"sv_qwmasterextra2",
"qwmaster.fodquake.net:27000",
"QW master in Germany, same IP as asgaard.morphos-team.net, admin: bigfoot"},
65 {
CF_CLIENT,
"sv_qwmasterextra3",
"master.quakeworld.nu:27000",
"QW master in Sweden, admin: unknown"},
82cvar_t net_connecttimeout = {
CF_CLIENT |
CF_SERVER,
"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."};
84cvar_t net_connectfloodblockingtimeout = {
CF_SERVER,
"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."};
85cvar_t net_challengefloodblockingtimeout = {
CF_SERVER,
"net_challengefloodblockingtimeout",
"0.5",
"when a challenge packet is received, it will block all future challenge packets from that IP address for this many seconds (cuts down on challenge floods). DarkPlaces clients retry once per second, so this should be <= 1. Failure here may lead to connect attempts failing."};
86cvar_t net_getstatusfloodblockingtimeout = {
CF_SERVER,
"net_getstatusfloodblockingtimeout",
"1",
"when a getstatus packet is received, it will block all future getstatus packets from that IP address for this many seconds (cuts down on getstatus floods). DarkPlaces retries every net_slist_timeout seconds, and qstat retries once per second, so this should be <= 1. Failure here may lead to server not showing up in the server list."};
91cvar_t net_fakelag = {
CF_CLIENT,
"net_fakelag",
"0",
"lags local loopback connection by this much ping time (useful to play more fairly on your own server with people with higher pings)"};
92static cvar_t net_fakeloss_send = {
CF_CLIENT,
"net_fakeloss_send",
"0",
"drops this percentage of outgoing packets, useful for testing network protocol robustness (jerky movement, prediction errors, etc)"};
93static cvar_t net_fakeloss_receive = {
CF_CLIENT,
"net_fakeloss_receive",
"0",
"drops this percentage of incoming packets, useful for testing network protocol robustness (jerky movement, effects failing to start, sounds failing to play, etc)"};
96static cvar_t net_slist_debug = {
CF_CLIENT,
"net_slist_debug",
"0",
"enables verbose messages for master server queries"};
97static cvar_t net_slist_favorites = {
CF_CLIENT |
CF_ARCHIVE,
"net_slist_favorites",
"",
"contains a list of IP addresses and ports to always query explicitly"};
98static 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"};
99static 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"};
100static 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)"};
101static 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"};
102static cvar_t net_slist_queriespersecond = {
CF_CLIENT,
"net_slist_queriespersecond",
"128",
"how many server information requests to send per second"};
103static cvar_t net_slist_queriesperframe = {
CF_CLIENT,
"net_slist_queriesperframe",
"2",
"maximum number of server information requests to send each rendered frame (guards against low framerates causing problems)"};
104static cvar_t net_slist_timeout = {
CF_CLIENT,
"net_slist_timeout",
"4",
"minimum number of seconds to wait between status queries to the same QW server, determines which response belongs to which query so low values will cause impossible pings; also a warning is printed if a dpmaster query fails to complete within this time"};
109static cvar_t gameversion_min = {
CF_CLIENT |
CF_SERVER,
"gameversion_min",
"-1",
"minimum version of game data (mod-specific), when client and server gameversion mismatch in the server browser the server is shown as incompatible; if -1, gameversion is used alone"};
110static cvar_t gameversion_max = {
CF_CLIENT |
CF_SERVER,
"gameversion_max",
"-1",
"maximum version of game data (mod-specific), when client and server gameversion mismatch in the server browser the server is shown as incompatible; if -1, gameversion is used alone"};
111static cvar_t rcon_restricted_password = {
CF_SERVER |
CF_PRIVATE,
"rcon_restricted_password",
"",
"password to authenticate rcon commands in restricted mode; may be set to a string of the form user1:pass1 user2:pass2 user3:pass3 to allow multiple user accounts - the client then has to specify ONE of these combinations"};
113static cvar_t rcon_secure_maxdiff = {
CF_SERVER,
"rcon_secure_maxdiff",
"5",
"maximum time difference between rcon request and server system clock (to protect against replay attack)"};
125#define DPMASTER_COUNT sizeof(sv_masters) / sizeof(cvar_t)
126#define QWMASTER_COUNT sizeof(sv_qwmasters) / sizeof(cvar_t)
132#define SLIST_QUERYSTAGE_DPMASTERS 1
133#define SLIST_QUERYSTAGE_QWMASTERS 2
134#define SLIST_QUERYSTAGE_SERVERS 4
138#define MASTER_TX_QUERY 1
139#define MASTER_RX_RESPONSE 2
140#define MASTER_RX_COMPLETE 3
143char serverlist_dpserverquerykey[12];
173serverlist_infofield_t serverlist_sortbyfield;
174unsigned serverlist_sortflags;
176unsigned serverlist_viewcount = 0;
177uint16_t serverlist_viewlist[SERVERLIST_VIEWLISTSIZE];
179unsigned serverlist_maxcachecount = 0;
180unsigned serverlist_cachecount = 0;
181serverlist_entry_t *serverlist_cache =
NULL;
183static qbool serverlist_consoleoutput;
185static unsigned nFavorites = 0;
187static unsigned nFavorites_idfp = 0;
190void NetConn_UpdateFavorites_c(
cvar_t *var)
202 dp_strlcpy(favorites_idfp[nFavorites_idfp],
com_token,
sizeof(favorites_idfp[nFavorites_idfp]));
215static void _ServerList_ViewList_Helper_InsertBefore(
unsigned index, serverlist_entry_t *entry)
219 if( serverlist_viewcount < SERVERLIST_VIEWLISTSIZE ) {
220 i = serverlist_viewcount++;
222 i = SERVERLIST_VIEWLISTSIZE - 1;
226 serverlist_viewlist[
i ] = serverlist_viewlist[
i - 1 ];
228 serverlist_viewlist[
index] = (
int)(entry - serverlist_cache);
232static inline void _ServerList_ViewList_Helper_Remove(
unsigned index)
234 serverlist_viewcount--;
235 for( ;
index < serverlist_viewcount ;
index++ )
236 serverlist_viewlist[
index] = serverlist_viewlist[
index + 1];
240static qbool _ServerList_Entry_Compare( serverlist_entry_t *A, serverlist_entry_t *B )
246 result = A->info.category - B->info.category;
253 if(A->info.isfavorite != B->info.isfavorite)
254 return A->info.isfavorite;
257 switch( serverlist_sortbyfield ) {
259 result = A->info.ping - B->info.ping;
261 case SLIF_MAXPLAYERS:
262 result = A->info.maxplayers - B->info.maxplayers;
264 case SLIF_NUMPLAYERS:
265 result = A->info.numplayers - B->info.numplayers;
268 result = A->info.numbots - B->info.numbots;
271 result = A->info.numhumans - B->info.numhumans;
274 result = A->info.freeslots - B->info.freeslots;
277 result = A->info.protocol - B->info.protocol;
280 result = strcmp( B->info.cname, A->info.cname );
283 result = strcasecmp( B->info.game, A->info.game );
286 result = strcasecmp( B->info.map, A->info.map );
289 result = strcasecmp( B->info.mod, A->info.mod );
292 result = strcasecmp( B->info.name, A->info.name );
295 result = strcasecmp( B->info.qcstatus, A->info.qcstatus );
298 result = A->info.category - B->info.category;
300 case SLIF_ISFAVORITE:
301 result = !!B->info.isfavorite - !!A->info.isfavorite;
304 Con_DPrint(
"_ServerList_Entry_Compare: Bad serverlist_sortbyfield!\n" );
322static qbool _ServerList_CompareInt(
int A, serverlist_maskop_t op,
int B )
336 case SLMO_GREATEREQUAL:
338 case SLMO_NOTCONTAIN:
339 case SLMO_STARTSWITH:
340 case SLMO_NOTSTARTSWITH:
343 Con_DPrint(
"_ServerList_CompareInt: Bad op!\n" );
348static qbool _ServerList_CompareStr(
const char *A, serverlist_maskop_t op,
const char *B )
351 char bufferA[ 1400 ], bufferB[ 1400 ];
353 for (
i = 0;
i < (
int)
sizeof(bufferA)-1 && bufferA[
i];
i++)
354 bufferA[
i] = (bufferA[
i] >=
'A' && bufferA[
i] <=
'Z') ? (bufferA[
i] +
'a' -
'A') : bufferA[
i];
356 for (
i = 0;
i < (
int)
sizeof(bufferB)-1 && B[
i];
i++)
357 bufferB[
i] = (B[
i] >=
'A' && B[
i] <=
'Z') ? (B[
i] +
'a' -
'A') : B[
i];
364 return *bufferB && !!strstr( bufferA, bufferB );
365 case SLMO_NOTCONTAIN:
366 return !*bufferB || !strstr( bufferA, bufferB );
367 case SLMO_STARTSWITH:
369 return *bufferB && !memcmp(bufferA, bufferB,
strlen(bufferB));
370 case SLMO_NOTSTARTSWITH:
371 return !*bufferB || memcmp(bufferA, bufferB,
strlen(bufferB));
373 return strcmp( bufferA, bufferB ) < 0;
375 return strcmp( bufferA, bufferB ) <= 0;
377 return strcmp( bufferA, bufferB ) == 0;
379 return strcmp( bufferA, bufferB ) > 0;
381 return strcmp( bufferA, bufferB ) != 0;
382 case SLMO_GREATEREQUAL:
383 return strcmp( bufferA, bufferB ) >= 0;
385 Con_DPrint(
"_ServerList_CompareStr: Bad op!\n" );
390static qbool _ServerList_Entry_Mask( serverlist_mask_t *
mask, serverlist_info_t *info )
392 if( !_ServerList_CompareInt( info->ping,
mask->tests[SLIF_PING],
mask->info.ping ) )
394 if( !_ServerList_CompareInt( info->maxplayers,
mask->tests[SLIF_MAXPLAYERS],
mask->info.maxplayers ) )
396 if( !_ServerList_CompareInt( info->numplayers,
mask->tests[SLIF_NUMPLAYERS],
mask->info.numplayers ) )
398 if( !_ServerList_CompareInt( info->numbots,
mask->tests[SLIF_NUMBOTS],
mask->info.numbots ) )
400 if( !_ServerList_CompareInt( info->numhumans,
mask->tests[SLIF_NUMHUMANS],
mask->info.numhumans ) )
402 if( !_ServerList_CompareInt( info->freeslots,
mask->tests[SLIF_FREESLOTS],
mask->info.freeslots ) )
404 if( !_ServerList_CompareInt( info->protocol,
mask->tests[SLIF_PROTOCOL],
mask->info.protocol ))
406 if( *
mask->info.cname
407 && !_ServerList_CompareStr( info->cname,
mask->tests[SLIF_CNAME],
mask->info.cname ) )
410 && !_ServerList_CompareStr( info->game,
mask->tests[SLIF_GAME],
mask->info.game ) )
413 && !_ServerList_CompareStr( info->mod,
mask->tests[SLIF_MOD],
mask->info.mod ) )
416 && !_ServerList_CompareStr( info->map,
mask->tests[SLIF_MAP],
mask->info.map ) )
419 && !_ServerList_CompareStr( info->name,
mask->tests[SLIF_NAME],
mask->info.name ) )
421 if( *
mask->info.qcstatus
422 && !_ServerList_CompareStr( info->qcstatus,
mask->tests[SLIF_QCSTATUS],
mask->info.qcstatus ) )
424 if( *
mask->info.players
425 && !_ServerList_CompareStr( info->players,
mask->tests[SLIF_PLAYERS],
mask->info.players ) )
427 if( !_ServerList_CompareInt( info->category,
mask->tests[SLIF_CATEGORY],
mask->info.category ) )
429 if( !_ServerList_CompareInt( info->isfavorite,
mask->tests[SLIF_ISFAVORITE],
mask->info.isfavorite ))
434static void ServerList_ViewList_Insert( serverlist_entry_t *entry )
436 unsigned start, end, mid,
i;
454 if (!entry->info.ping)
458 entry->info.isfavorite =
false;
462 for(
i = 0;
i < nFavorites; ++
i)
466 entry->info.isfavorite =
true;
472 for(
i = 0;
i < nFavorites_idfp; ++
i)
474 if(!strcmp(idfp, favorites_idfp[
i]))
476 entry->info.isfavorite =
true;
489 if( !_ServerList_Entry_Mask( &serverlist_andmasks[start], &entry->info ) )
493 if( _ServerList_Entry_Mask( &serverlist_ormasks[start], &entry->info ) )
498 if( !serverlist_viewcount ) {
499 _ServerList_ViewList_Helper_InsertBefore( 0, entry );
506 if( _ServerList_Entry_Compare( entry, ServerList_GetViewEntry(0) ) ) {
507 _ServerList_ViewList_Helper_InsertBefore( 0, entry );
510 else if( !_ServerList_Entry_Compare( entry, ServerList_GetViewEntry(serverlist_viewcount - 1) ) ) {
511 _ServerList_ViewList_Helper_InsertBefore( serverlist_viewcount, entry );
515 end = serverlist_viewcount - 1;
516 while( end > start + 1 )
518 mid = (start + end) / 2;
520 if( _ServerList_Entry_Compare( entry, ServerList_GetViewEntry(mid) ) )
527 _ServerList_ViewList_Helper_InsertBefore( start + 1, entry );
530static void ServerList_ViewList_Remove( serverlist_entry_t *entry )
534 for(
i = 0;
i < serverlist_viewcount;
i++ )
536 if (ServerList_GetViewEntry(
i) == entry)
538 _ServerList_ViewList_Helper_Remove(
i);
544void ServerList_RebuildViewList(
cvar_t *var)
551 serverlist_viewcount = 0;
552 for (
i = 0;
i < serverlist_cachecount; ++
i)
553 ServerList_ViewList_Insert(&serverlist_cache[
i]);
556void ServerList_ResetMasks(
void)
560 memset( &serverlist_andmasks, 0,
sizeof( serverlist_andmasks ) );
561 memset( &serverlist_ormasks, 0,
sizeof( serverlist_ormasks ) );
564 serverlist_andmasks[
i].info.numbots = -1;
566 serverlist_ormasks[
i].info.numbots = -1;
569void ServerList_GetPlayerStatistics(
unsigned *numplayerspointer,
unsigned *maxplayerspointer)
574 for (
i = 0;
i < serverlist_cachecount;
i++)
576 if (serverlist_cache[
i].info.ping)
578 numplayers += serverlist_cache[
i].info.numhumans;
582 *numplayerspointer = numplayers;
587static void _ServerList_Test(
void)
590 if (serverlist_maxcachecount <= 1024)
592 serverlist_maxcachecount = 1024;
593 serverlist_cache = (serverlist_entry_t *)
Mem_Realloc(
netconn_mempool, (
void *)serverlist_cache,
sizeof(serverlist_entry_t) * serverlist_maxcachecount);
595 for(
i = 0 ;
i < 1024 ;
i++ ) {
596 memset( &serverlist_cache[serverlist_cachecount], 0,
sizeof( serverlist_entry_t ) );
597 serverlist_cache[serverlist_cachecount].info.ping = 1000 + 1024 -
i;
598 dpsnprintf( serverlist_cache[serverlist_cachecount].info.name,
sizeof(serverlist_cache[serverlist_cachecount].info.name),
"Black's ServerList Test %i",
i );
599 serverlist_cache[serverlist_cachecount].finished =
true;
600 dpsnprintf( serverlist_cache[serverlist_cachecount].line1,
sizeof(serverlist_cache[serverlist_cachecount].info.line1),
"%i %s", serverlist_cache[serverlist_cachecount].info.ping, serverlist_cache[serverlist_cachecount].info.name );
601 ServerList_ViewList_Insert( &serverlist_cache[serverlist_cachecount] );
602 serverlist_cachecount++;
623static inline void ServerList_BuildDPServerQuery(
char *
buffer,
size_t buffersize,
double querytime)
625 unsigned char hash[24];
626 uint64_t timestamp = querytime * 1000.0;
629 (
unsigned char *)×tamp,
sizeof(timestamp),
630 (
unsigned char *)serverlist_dpserverquerykey,
sizeof(serverlist_dpserverquerykey));
632 dpsnprintf(
buffer, buffersize,
"\377\377\377\377getstatus %.22s%" PRIx64, hash, timestamp);
646 serverlist_cachecount = 0;
647 serverlist_viewcount = 0;
648 serverlist_maxcachecount = 0;
649 serverlist_cache = (serverlist_entry_t *)
Mem_Realloc(
netconn_mempool, (
void *)serverlist_cache,
sizeof(serverlist_entry_t) * serverlist_maxcachecount);
661 for (
i = 0;
i < serverlist_cachecount; ++
i)
662 serverlist_cache[
i].responded =
false;
664 serverlist_querystage = (querydp ? SLIST_QUERYSTAGE_DPMASTERS : 0) | (queryqw ? SLIST_QUERYSTAGE_QWMASTERS : 0);
667 serverlist_consoleoutput = consoleoutput;
669 Con_Printf(
"^2Querying %s master, favourite and LAN servers, reset=%u\n",
670 querydp && queryqw ?
"DP and QW" : querydp ?
"DP" :
"QW",
675 NetConn_QueryMasters(querydp, queryqw);
687 ServerList_BuildDPServerQuery(dpquery,
sizeof(dpquery),
masterquerytime);
744 char addressstring[128], addressstring2[128];
749 Con_Printf(
"LHNET_Read(%p (%s), %p, %i, %p) = %i from %s:\n", (
void *)mysocket, addressstring, (
void *)
data, maxlength, (
void *)peeraddress,
length, addressstring2);
753 Con_Printf(
"LHNET_Read(%p (%s), %p, %i, %p) = %i\n", (
void *)mysocket, addressstring, (
void *)
data, maxlength, (
void *)peeraddress,
length);
774 char addressstring[128], addressstring2[128];
777 Con_Printf(
"LHNET_Write(%p (%s), %p, %i, %p (%s)) = %i%s\n", (
void *)mysocket, addressstring, (
void *)
data,
length, (
void *)peeraddress, addressstring2,
length,
ret ==
length ?
"" :
" (ERROR)");
808 double bursttime = burstsize / (double)rate;
813 *cleartime = *cleartime + len / (double)rate;
833 int r = rand() % 7 + 1;
866 sendreliable =
false;
895 Con_Printf (
"NetConn_SendUnreliableMessage: reliable message too big %u\n",
data->cursize);
911 if (packetLen +
data->cursize <= 1400)
914 memcpy(sendbuffer + packetLen,
data->data,
data->cursize);
915 packetLen +=
data->cursize;
923 totallen += packetLen + 28;
927 unsigned int packetLen;
928 unsigned int dataLen;
955 sendme =
Crypto_EncryptPacket(&conn->
crypto, &sendbuffer, packetLen, &cryptosendbuffer, &sendmelen,
sizeof(cryptosendbuffer));
962 totallen += (
int)sendmelen + 28;
977 Con_Print(
"client sending reliable message to server:\n");
1006 sendme =
Crypto_EncryptPacket(&conn->
crypto, &sendbuffer, packetLen, &cryptosendbuffer, &sendmelen,
sizeof(cryptosendbuffer));
1014 totallen += (
int)sendmelen + 28;
1022 if (packetLen > (
int)
sizeof(sendbuffer))
1024 Con_Printf(
"NetConn_SendUnreliableMessage: message too big %u\n",
data->cursize);
1036 sendme =
Crypto_EncryptPacket(&conn->
crypto, &sendbuffer, packetLen, &cryptosendbuffer, &sendmelen,
sizeof(cryptosendbuffer));
1043 totallen += (
int)sendmelen + 28;
1074 char addressstring2[1024];
1075 if (addressstring && addressstring[0])
1086 Con_Printf(
"Client opened a socket on address %s\n", addressstring2);
1111 Con_Printf(
"Client using an automatically assigned port\n");
1116#ifndef NOSUPPORTIPV6
1133 char addressstring2[1024];
1136 for (port = defaultport; port <= defaultport + range; port++)
1138 if (addressstring && addressstring[0])
1149 Con_Printf(
"Server listening on address %s\n", addressstring2);
1187#ifndef NOSUPPORTIPV6
1195 Host_Error(
"NetConn_OpenServerPorts: unable to open any ports!");
1254 if (c->
next == conn)
1280 Con_Print(
"Changing \"cl_port\" will not take effect until you reconnect.\n");
1302 Con_Print(
"Changing \"port\" will not take effect until \"map\" command is executed.\n");
1342 unsigned int sequence, sequence_ack;
1343 qbool reliable_ack, reliable_message;
1364 reliable_message = (sequence >> 31) != 0;
1365 reliable_ack = (sequence_ack >> 31) != 0;
1366 sequence &= ~(1u<<31);
1367 sequence_ack &= ~(1u<<31);
1368 if (sequence <= conn->qw.incoming_sequence)
1420 if (reliable_message)
1443 unsigned int sequence;
1456 flags = qlength & ~NETFLAG_LENGTH_MASK;
1539 unsigned int packetLen;
1540 unsigned int dataLen;
1565 sendme =
Crypto_EncryptPacket(&conn->
crypto, &sendbuffer, packetLen, &cryptosendbuffer, &sendmelen,
sizeof(cryptosendbuffer));
1584 unsigned char temppacket[8];
1604 Con_Printf(
"Reliable message (seq: %i) too big for message buffer!\n"
1605 "Dropping the message!\n", sequence );
1656 Con_Printf(
"%s connection to %s has been established: server is %s@%s%.*s, I am %.*s@%s%.*s\n",
1657 crypto->
use_aes ?
"Encrypted" :
"Authenticated",
1687 unsigned char buf[4];
1688 memset(&msg, 0,
sizeof(msg));
1705static int NetConn_ClientParsePacket_ServerList_ProcessReply(
const char *addressstring,
const char *challenge)
1709 double currentrealtime;
1710 serverlist_entry_t *entry;
1713 for (
n = 0;
n < serverlist_cachecount; ++
n)
1715 entry = &serverlist_cache[
n];
1716 if (!strcmp(addressstring, entry->info.cname))
1720 if (
n == serverlist_cachecount)
1723 Con_Printf(
"^6Received reply from unlisted %sserver %s\n", challenge ?
"DarkPlaces " :
"", addressstring);
1729 if (serverlist_maxcachecount <= serverlist_cachecount)
1731 serverlist_maxcachecount += 64;
1732 serverlist_cache = (serverlist_entry_t *)
Mem_Realloc(
netconn_mempool, (
void *)serverlist_cache,
sizeof(serverlist_entry_t) * serverlist_maxcachecount);
1734 ++serverlist_cachecount;
1735 entry = &serverlist_cache[
n];
1737 memset(entry, 0,
sizeof(*entry));
1738 entry->info.cname_len =
dp_strlcpy(entry->info.cname, addressstring,
sizeof(entry->info.cname));
1746 if (serverlist_consoleoutput)
1756 unsigned char hash[24];
1757 uint64_t timestamp = strtoull(&challenge[22],
NULL, 16);
1760 (
unsigned char *)×tamp,
sizeof(timestamp),
1761 (
unsigned char *)serverlist_dpserverquerykey,
sizeof(serverlist_dpserverquerykey));
1763 if (memcmp(hash, challenge, 22) != 0)
1766 ping = currentrealtime * 1000.0 - timestamp;
1769 ping = 1000 * (currentrealtime - entry->querytime);
1772 || (entry->info.ping &&
ping > entry->info.ping + 100))
1779 if (entry->info.ping)
1780 entry->info.ping = (entry->info.ping +
ping) * 0.5 + 0.5;
1783 entry->info.ping =
ping + 0.5;
1786 entry->responded =
true;
1792static void NetConn_ClientParsePacket_ServerList_UpdateCache(
int n)
1794 serverlist_entry_t *entry = &serverlist_cache[
n];
1795 serverlist_info_t *info = &entry->info;
1798 entry->line1_len =
dpsnprintf(entry->line1,
sizeof(serverlist_cache[
n].line1),
"^%c%5.0f^7 ^%c%3u^7/%3u %-65.65s",
1799 info->ping >= 300 ?
'1' : (info->ping >= 200 ?
'3' :
'7'),
1800 info->ping ? info->ping : INFINITY,
1801 ((info->numhumans > 0 && info->numhumans < info->maxplayers) ? (info->numhumans >= 4 ?
'7' :
'3') :
'1'),
1805 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,
1816 info->mod, info->map);
1820 ServerList_ViewList_Remove(entry);
1821 ServerList_ViewList_Insert(entry);
1824 if (serverlist_consoleoutput)
1825 Con_Printf(
"%s\n%s\n", entry->line1, entry->line2);
1829static qbool NetConn_ClientParsePacket_ServerList_PrepareQuery(
int protocol,
const char *ipstring,
qbool isfavorite)
1832 serverlist_entry_t *entry;
1838 for (
n = 0;
n < serverlist_cachecount; ++
n)
1839 if (!strcmp(ipstring, serverlist_cache[
n].info.cname))
1843 if (
n < serverlist_cachecount)
1846 if (serverlist_maxcachecount <=
n)
1848 serverlist_maxcachecount += 64;
1849 serverlist_cache = (serverlist_entry_t *)
Mem_Realloc(
netconn_mempool, (
void *)serverlist_cache,
sizeof(serverlist_entry_t) * serverlist_maxcachecount);
1852 entry = &serverlist_cache[
n];
1853 memset(entry, 0,
sizeof(*entry));
1854 entry->protocol = protocol;
1855 entry->info.cname_len =
dp_strlcpy(entry->info.cname, ipstring,
sizeof(entry->info.cname));
1856 entry->info.isfavorite = isfavorite;
1858 serverlist_cachecount++;
1864static void NetConn_ClientParsePacket_ServerList_ParseDPList(
lhnetaddress_t *masteraddress,
const char *masteraddressstring,
const unsigned char *
data,
int length,
qbool isextended)
1876 Con_Printf(
CON_WARN "ignoring DarkPlaces %sserver list from unrecognised master %s\n",
1877 isextended ?
"extended " :
"", masteraddressstring);
1882 if (dpmasterstatus[masternum] < MASTER_RX_RESPONSE)
1883 dpmasterstatus[masternum] = MASTER_RX_RESPONSE;
1885 if (dpmasterstatus[masternum] == MASTER_RX_COMPLETE)
1887 isextended ?
"(extended) " :
"",
sv_masters[masternum].
string);
1888 else if (serverlist_consoleoutput || net_slist_debug.
integer)
1889 Con_Printf(
"^5Received DarkPlaces server list %sfrom %s\n",
1890 isextended ?
"(extended) " :
"",
sv_masters[masternum].
string);
1894 char ipstring [128];
1897 if (
data[0] ==
'\\')
1899 unsigned short port =
data[5] * 256 +
data[6];
1901 if (port != 0 && (
data[1] != 0xFF ||
data[2] != 0xFF ||
data[3] != 0xFF ||
data[4] != 0xFF))
1903 else if (port == 0 &&
data[1] ==
'E' &&
data[2] ==
'O' &&
data[3] ==
'T' &&
data[4] ==
'\0')
1905 dpmasterstatus[masternum] = MASTER_RX_COMPLETE;
1907 Con_Printf(
"^4End Of Transmission %sfrom %s\n", isextended ?
"(extended) " :
"",
sv_masters[masternum].
string);
1916 else if (
data[0] ==
'/' && isextended &&
length >= 19)
1918 unsigned short port =
data[17] * 256 +
data[18];
1931 dpsnprintf (ipstring,
sizeof (ipstring),
"[%x:%x:%x:%x:%x:%x:%x:%x%%%s]:%hu",
1939 dpsnprintf (ipstring,
sizeof (ipstring),
"[%x:%x:%x:%x:%x:%x:%x:%x]:%hu",
1957 Con_Printf(
"Requesting info from DarkPlaces server %s\n", ipstring);
1967 if (dpmasterstatus[masternum] && dpmasterstatus[masternum] < MASTER_RX_COMPLETE)
1973 Con_Print(
"^2Starting to query servers early (got EOT from all masters)\n");
1977static void NetConn_ClientParsePacket_ServerList_ParseQWList(
lhnetaddress_t *masteraddress,
const char *masteraddressstring,
const unsigned char *
data,
int length)
1983 if (sv_qwmasters[masternum].
string[0]
1989 Con_Printf(
CON_WARN "ignoring QuakeWorld server list from unrecognised master %s\n", masteraddressstring);
1994 qwmasterstatus[masternum] = MASTER_RX_RESPONSE;
1995 if (serverlist_consoleoutput || net_slist_debug.
integer)
1996 Con_Printf(
"^5Received QuakeWorld server list from %s\n", sv_qwmasters[masternum].
string);
2004 Con_Printf(
"Requesting info from QuakeWorld server %s\n", ipstring);
2006 if (!NetConn_ClientParsePacket_ServerList_PrepareQuery(
PROTOCOL_QUAKEWORLD, ipstring,
false))
2023 char *
string, addressstring2[128];
2024 char stringbuf[16384];
2050 Con_Printf(
"NetConn_ClientParsePacket: %s sent us a command:\n", addressstring2);
2054 sendlength =
sizeof(senddata) - 4;
2063 memcpy(senddata,
"\377\377\377\377", 4);
2064 NetConn_Write(mysocket, senddata, (
int)sendlength+4, peeraddress);
2070 memcpy(senddata,
"\377\377\377\377", 4);
2071 NetConn_Write(mysocket, senddata, (
int)sendlength+4, peeraddress);
2076 string = senddata+4;
2099 memcpy(
buf,
"\377\377\377\377srcon HMAC-MD4 CHALLENGE ", 29);
2135 char protocolnames[1400];
2138 Con_Printf(
CON_WARN "ignoring challenge message from wrong server %s\n", addressstring2);
2141 Con_DPrintf(
"\"%s\" received, sending connect request back to %s\n",
string, addressstring2);
2148 memcpy(senddata,
"\377\377\377\377", 4);
2149 dpsnprintf(senddata+4,
sizeof(senddata)-4,
"connect\\protocol\\darkplaces 3\\protocols\\%s%s\\challenge\\%s", protocolnames,
cls.
connect_userinfo,
string + 10);
2157 Con_Printf(
CON_WARN "ignoring accept message from wrong server %s\n", addressstring2);
2166 Con_Printf(
CON_WARN "ignoring reject message from wrong server %s\n", addressstring2);
2179 if (
length >= 15 && !memcmp(
string,
"statusResponse\x0A", 15))
2181 serverlist_info_t *info;
2189 n = NetConn_ClientParsePacket_ServerList_ProcessReply(addressstring2, infostringvalue);
2193 info = &serverlist_cache[
n].info;
2194 p = strchr(
string,
'\n');
2199 info->players_len =
dp_strlcpy(info->players, p,
sizeof(info->players));
2203 Con_Printf(
"statusResponse without players block?\n");
2204 info->players_len = info->players[0] = 0;
2210 info->qcstatus_len =
InfoString_GetValue(
string,
"qcstatus", info->qcstatus,
sizeof(info->qcstatus));
2211 info->protocol =
InfoString_GetValue(
string,
"protocol" , infostringvalue,
sizeof(infostringvalue)) ? atoi(infostringvalue) : -1;
2212 info->numplayers =
InfoString_GetValue(
string,
"clients" , infostringvalue,
sizeof(infostringvalue)) ? atoi(infostringvalue) : 0;
2213 info->numbots =
InfoString_GetValue(
string,
"bots" , infostringvalue,
sizeof(infostringvalue)) ? atoi(infostringvalue) : -1;
2214 info->maxplayers =
InfoString_GetValue(
string,
"sv_maxclients", infostringvalue,
sizeof(infostringvalue)) ? atoi(infostringvalue) : 0;
2215 info->gameversion =
InfoString_GetValue(
string,
"gameversion" , infostringvalue,
sizeof(infostringvalue)) ? atoi(infostringvalue) : 0;
2216 info->numhumans = info->numplayers -
max(0, info->numbots);
2217 info->freeslots = info->maxplayers - info->numplayers;
2219 NetConn_ClientParsePacket_ServerList_UpdateCache(
n);
2223 if (
length >= 13 && !memcmp(
string,
"infoResponse\x0A", 13))
2225 serverlist_info_t *info;
2232 n = NetConn_ClientParsePacket_ServerList_ProcessReply(addressstring2, infostringvalue);
2236 info = &serverlist_cache[
n].info;
2237 info->players_len = info->players[0] = 0;
2242 info->qcstatus_len =
InfoString_GetValue(
string,
"qcstatus", info->qcstatus,
sizeof(info->qcstatus));
2243 info->protocol =
InfoString_GetValue(
string,
"protocol" , infostringvalue,
sizeof(infostringvalue)) ? atoi(infostringvalue) : -1;
2244 info->numplayers =
InfoString_GetValue(
string,
"clients" , infostringvalue,
sizeof(infostringvalue)) ? atoi(infostringvalue) : 0;
2245 info->numbots =
InfoString_GetValue(
string,
"bots" , infostringvalue,
sizeof(infostringvalue)) ? atoi(infostringvalue) : -1;
2246 info->maxplayers =
InfoString_GetValue(
string,
"sv_maxclients", infostringvalue,
sizeof(infostringvalue)) ? atoi(infostringvalue) : 0;
2247 info->gameversion =
InfoString_GetValue(
string,
"gameversion" , infostringvalue,
sizeof(infostringvalue)) ? atoi(infostringvalue) : 0;
2248 info->numhumans = info->numplayers -
max(0, info->numbots);
2249 info->freeslots = info->maxplayers - info->numplayers;
2251 NetConn_ClientParsePacket_ServerList_UpdateCache(
n);
2255 if (!strncmp(
string,
"getserversResponse\\", 19) && serverlist_cachecount <
SERVERLIST_TOTALSIZE)
2260 NetConn_ClientParsePacket_ServerList_ParseDPList(peeraddress, addressstring2,
data,
length,
false);
2263 if (!strncmp(
string,
"getserversExtResponse", 21) && serverlist_cachecount <
SERVERLIST_TOTALSIZE)
2268 NetConn_ClientParsePacket_ServerList_ParseDPList(peeraddress, addressstring2,
data,
length,
true);
2276 NetConn_ClientParsePacket_ServerList_ParseQWList(peeraddress, addressstring2,
data,
length);
2281 if (!strncmp(
string,
"extResponse ", 12))
2290 if (!strncmp(
string,
"ping", 4))
2293 Con_DPrintf(
"Received ping from %s, sending ack\n", addressstring2);
2297 if (!strncmp(
string,
"ack", 3))
2300 if (
length > 1 &&
string[0] ==
'c' && (
string[1] ==
'-' || (
string[1] >=
'0' &&
string[1] <=
'9')) &&
cls.
connect_trying)
2307 Con_DPrintf(
"challenge %s received, sending QuakeWorld connect request back to %s\n",
string + 1, addressstring2);
2313 memcpy(senddata,
"\377\377\377\377", 4);
2328 if (
length > 2 && !memcmp(
string,
"n\\", 2))
2331 serverlist_info_t *info;
2337 Con_Printf(
"QW server status from server at %s:\n%s\n", addressstring2,
string + 1);
2341 n = NetConn_ClientParsePacket_ServerList_ProcessReply(addressstring2,
NULL);
2345 info = &serverlist_cache[
n].info;
2346 dp_strlcpy(info->game,
"QuakeWorld",
sizeof(info->game));
2351 info->numplayers = 0;
2352 info->numhumans = 0;
2353 info->maxplayers =
InfoString_GetValue(
string,
"maxclients" , infostringvalue,
sizeof(infostringvalue)) ? atoi(infostringvalue) : 0;
2354 info->gameversion =
InfoString_GetValue(
string,
"gameversion", infostringvalue,
sizeof(infostringvalue)) ? atoi(infostringvalue) : 0;
2358 s = strchr(
string,
'\n');
2362 while (s <
string +
length)
2364 for (;s <
string +
length && *s !=
'\n';s++)
2366 if (s >=
string +
length)
2374 NetConn_ClientParsePacket_ServerList_UpdateCache(
n);
2378 if (
string[0] ==
'n')
2385 Con_Printf(
"QW print command from server at %s:\n%s\n", addressstring2,
string + 1);
2403 serverlist_info_t *info;
2416 Con_DPrintf(
"Datagram_ParseConnectionless: received CCREP_ACCEPT from %s.\n", addressstring2);
2421 Con_Printf(
CON_WARN "ignoring CCREP_ACCEPT message from wrong server %s\n", addressstring2);
2424 clientportaddress = *peeraddress;
2449 Con_Printf(
CON_WARN "ignoring CCREP_REJECT message from wrong server %s\n", addressstring2);
2458 Con_DPrintf(
"Datagram_ParseConnectionless: received CCREP_SERVER_INFO from %s.\n", addressstring2);
2464 n = NetConn_ClientParsePacket_ServerList_ProcessReply(addressstring2,
NULL);
2468 info = &serverlist_cache[
n].info;
2469 info->game_len =
dp_strlcpy(info->game,
"Quake",
sizeof(info->game));
2470 info->mod_len =
dp_strlcpy(info->mod,
"",
sizeof(info->mod));
2477 NetConn_ClientParsePacket_ServerList_UpdateCache(
n);
2482 Con_Printf(
CON_WARN "ignoring CCREP_RCON message from wrong server %s\n", addressstring2);
2486 Con_DPrintf(
"Datagram_ParseConnectionless: received CCREP_RCON from %s.\n", addressstring2);
2493 Con_Printf(
"Datagram_ParseConnectionless: received CCREP_PLAYER_INFO from %s.\n", addressstring2);
2498 Con_Printf(
"Datagram_ParseConnectionless: received CCREP_RULE_INFO from %s.\n", addressstring2);
2515void NetConn_QueryQueueFrame(
void)
2518 unsigned maxqueries;
2520 double currentrealtime;
2521 static double querycounter = 0;
2522 static unsigned pass = 0, server = 0;
2523 unsigned queriesperserver =
bound(1, net_slist_maxtries.
integer, 8);
2546 if (dpmasterstatus[
index] == MASTER_TX_QUERY)
2548 if (net_slist_debug.
integer ||
2553 else if (dpmasterstatus[
index] && dpmasterstatus[
index] < MASTER_RX_COMPLETE)
2558 if (qwmasterstatus[
index] && qwmasterstatus[
index] < MASTER_RX_RESPONSE
2568 maxqueries =
bound(0, (
int)querycounter, net_slist_queriesperframe.
integer);
2569 querycounter -= maxqueries;
2570 if (maxqueries == 0)
2573 if (pass < queriesperserver)
2577 ServerList_BuildDPServerQuery(dpquery,
sizeof(dpquery), currentrealtime);
2579 for (
unsigned queries = 0; server < serverlist_cachecount; ++server)
2583 serverlist_entry_t *entry = &serverlist_cache[server];
2585 if (queries >= maxqueries
2586 || currentrealtime <= entry->querytime + (entry->protocol ==
PROTOCOL_QUAKEWORLD ? net_slist_timeout : net_slist_interval).value)
2603 entry->querytime = currentrealtime;
2606 if (serverlist_consoleoutput)
2607 Con_Printf(
"querying %25s (%i. try)\n", entry->info.cname, pass + 1);
2613 for (; server < serverlist_cachecount; ++server)
2615 serverlist_entry_t *entry = &serverlist_cache[server];
2617 if (!entry->responded
2618 && entry->info.ping)
2620 if (currentrealtime > entry->querytime + net_slist_maxping.
value/1000.0f)
2627 Con_Printf(
CON_WARN "Removing timed out server %s from viewlist\n", entry->info.cname);
2628 ServerList_ViewList_Remove(entry);
2630 entry->info.ping = 0;
2643 if (pass == queriesperserver)
2648 int dpmastersqueried = 0, qwmastersqueried = 0;
2651 if (dpmasterstatus[
index])
2654 if (qwmasterstatus[
index])
2656 Con_Printf(
"^2Finished querying %i DP %i QW masters and %i servers in %f seconds\n",
2657 dpmastersqueried, qwmastersqueried, serverlist_cachecount, currentrealtime -
masterquerytime);
2660 else if (pass > queriesperserver)
2665 if (net_slist_debug.
integer && serverlist_cachecount)
2666 Con_Printf(
"^4Finished checking server timeouts in %f\n",
2667 currentrealtime - serverlist_cache[serverlist_cachecount - 1].querytime);
2735 NetConn_QueryQueueFrame();
2745 for (
i = 0;
i < bufferlength - 1;
i++)
2749 c = rand () % (127 - 33) + 33;
2750 }
while (c ==
'\\' || c ==
';' || c ==
'"' || c ==
'%' || c ==
'/');
2761 unsigned int nb_clients = 0, nb_bots = 0,
i;
2765 const char *worldstatusstr;
2780 if(worldstatusstr && *worldstatusstr)
2785 for(q = worldstatusstr; *q && (size_t)(p - qcstatus) < (
sizeof(qcstatus) - 1); ++q)
2786 if(*q !=
'\\' && *q !=
'\n')
2794 "\377\377\377\377%s\x0A"
2795 "\\gamename\\%s\\modname\\%s\\gameversion\\%d\\sv_maxclients\\%d"
2796 "\\clients\\%d\\bots\\%d\\mapname\\%s\\hostname\\%s\\protocol\\%d"
2801 fullstatus ?
"statusResponse" :
"infoResponse",
2804 *qcstatus ?
"\\qcstatus\\" :
"", qcstatus,
2805 challenge ?
"\\challenge\\" :
"", challenge ? challenge :
"",
2807 fullstatus ?
"\n" :
"");
2829 int nameind, cleanind, pingvalue;
2831 char cleanname [
sizeof(client->
name)];
2832 const char *statusstr;
2840 curchar = client->
name[nameind++];
2841 if (curchar !=
'"' && curchar !=
'\\')
2843 cleanname[cleanind++] = curchar;
2844 if (cleanind ==
sizeof(cleanname) - 1)
2847 }
while (curchar !=
'\0');
2848 cleanname[cleanind] = 0;
2850 pingvalue = (
int)(client->
ping * 1000.0f);
2852 pingvalue =
bound(1, pingvalue, 9999);
2859 if(statusstr && *statusstr)
2864 for(q = statusstr; *q && p != qcstatus +
sizeof(qcstatus) - 1; ++q)
2872 if(client->
frags == -666)
2874 else if(client->
colors == 0x44)
2876 else if(client->
colors == 0xDD)
2878 else if(client->
colors == 0xCC)
2880 else if(client->
colors == 0x99)
2906 out_msg[savelength] = 0;
2907 memcpy(out_msg + 4,
"infoResponse\x0A", 13);
2908 memmove(out_msg + 17, out_msg + 19, savelength - 19);
2925 size_t floodslotnum, bestfloodslotnum;
2926 double bestfloodtime;
2929 noportpeeraddress = *peeraddress;
2931 bestfloodslotnum = 0;
2932 bestfloodtime = floodlist[bestfloodslotnum].
lasttime;
2933 for (floodslotnum = 0;floodslotnum < floodlength;floodslotnum++)
2935 if (bestfloodtime >= floodlist[floodslotnum].lasttime)
2937 bestfloodtime = floodlist[floodslotnum].
lasttime;
2938 bestfloodslotnum = floodslotnum;
2940 if (floodlist[floodslotnum].lasttime &&
LHNETADDRESS_Compare(&noportpeeraddress, &floodlist[floodslotnum].address) == 0)
2955 bestfloodslotnum = floodslotnum;
2960 floodlist[bestfloodslotnum].
address = noportpeeraddress;
2968 size_t floodslotnum;
2971 noportpeeraddress = *peeraddress;
2973 for (floodslotnum = 0;floodslotnum < floodlength;floodslotnum++)
2975 if (floodlist[floodslotnum].lasttime &&
LHNETADDRESS_Compare(&noportpeeraddress, &floodlist[floodslotnum].address) == 0)
2980 floodlist[floodslotnum].
lasttime = 0;
2994 Con_Print(
CON_ERROR "LOGIC ERROR: RCon_Authenticate should never call the comparator with an empty password. Please report.\n");
2999 t2 = strtol(s,
NULL, 0);
3003 if(!
HMAC_MDFOUR_16BYTES((
unsigned char *) mdfourbuf, (
unsigned char *) s, slen, (
unsigned char *) password, (
int)
strlen(password)))
3006 return !memcmp(mdfourbuf, hash, 16);
3015 Con_Print(
CON_ERROR "LOGIC ERROR: RCon_Authenticate should never call the comparator with an empty password. Please report.\n");
3019 if(slen < (
int)(
sizeof(
challenges[0].
string)) - 1)
3031 if(!
HMAC_MDFOUR_16BYTES((
unsigned char *) mdfourbuf, (
unsigned char *) s, slen, (
unsigned char *) password, (
int)
strlen(password)))
3034 if(memcmp(mdfourbuf, hash, 16))
3046 Con_Print(
CON_ERROR "LOGIC ERROR: RCon_Authenticate should never call the comparator with an empty password. Please report.\n");
3050 return !strcmp(password, hash);
3056 const char *text, *userpass_start, *userpass_end, *userpass_startpass;
3059 qbool restricted =
false;
3060 qbool have_usernames =
false;
3061 static char vabuf[1024];
3064 while((userpass_end = strchr(userpass_start,
' ')))
3066 have_usernames =
true;
3069 if(comparator(peeraddress,
buf, password, cs, cslen))
3071 userpass_start = userpass_end + 1;
3073 if(userpass_start[0])
3075 userpass_end = userpass_start +
strlen(userpass_start);
3076 if(comparator(peeraddress, userpass_start, password, cs, cslen))
3081 have_usernames =
false;
3083 while((userpass_end = strchr(userpass_start,
' ')))
3085 have_usernames =
true;
3088 if(comparator(peeraddress,
buf, password, cs, cslen))
3090 userpass_start = userpass_end + 1;
3092 if(userpass_start[0])
3094 userpass_end = userpass_start +
strlen(userpass_start);
3095 if(comparator(peeraddress, userpass_start, password, cs, cslen))
3102 for(text = s; text != endpos; ++text)
3103 if((
signed char) *text > 0 && ((
signed char) *text < (
signed char)
' ' || *text ==
';'))
3111 hasquotes = (strchr(s,
'"') !=
NULL);
3145 userpass_startpass = strchr(userpass_start,
':');
3146 if(have_usernames && userpass_startpass && userpass_startpass < userpass_end)
3147 return va(vabuf,
sizeof(vabuf),
"%srcon (username %.*s)", restricted ?
"restricted " :
"", (
int)(userpass_startpass-userpass_start), userpass_start);
3149 return va(vabuf,
sizeof(vabuf),
"%srcon", restricted ?
"restricted " :
"");
3157 const char *s_ptr = s;
3159 while(s_ptr != endpos)
3161 size_t l =
strlen(s_ptr);
3195 int i,
ret, clientnum, best;
3197 char *
string, response[2800], addressstring2[128];
3198 static char stringbuf[16384];
3201 size_t sendlength, response_len;
3232 Con_Printf(
"NetConn_ServerParsePacket: %s sent us a command:\n", addressstring2);
3236 sendlength =
sizeof(senddata) - 4;
3245 memcpy(senddata,
"\377\377\377\377", 4);
3246 NetConn_Write(mysocket, senddata, (
int)sendlength+4, peeraddress);
3252 memcpy(senddata,
"\377\377\377\377", 4);
3253 NetConn_Write(mysocket, senddata, (
int)sendlength+4, peeraddress);
3258 string = senddata+4;
3289 memcpy(response,
"\377\377\377\377", 4);
3291 response_len =
strlen(response) + 1;
3293 NetConn_Write(mysocket, response, (
int)response_len, peeraddress);
3296 if (
length > 8 && !memcmp(
string,
"connect\\", 8))
3308 Con_Printf(
"%s connection to %s is being established: client is %s@%s%.*s, I am %.*s@%s%.*s\n",
3309 crypto->
use_aes ?
"Encrypted" :
"Authenticated",
3336 Con_DPrintf(
"Connecting client %s sent us the message: %s\n", addressstring2, infostringvalue);
3342 memcpy(response,
"\377\377\377\377", 4);
3349 if(!
InfoString_GetValue(
string,
"protocol", infostringvalue,
sizeof(infostringvalue)) || strcmp(infostringvalue,
"darkplaces 3"))
3352 Con_Printf(
"Datagram_ParseConnectionless: sending \"reject Wrong game protocol.\" to %s.\n", addressstring2);
3353 NetConn_WriteString(mysocket,
"\377\377\377\377reject Wrong game protocol.", peeraddress);
3380 Con_Printf(
"Datagram_ParseConnectionless: sending \"reject Attempt to change key of crypto.\" to %s.\n", addressstring2);
3381 NetConn_WriteString(mysocket,
"\377\377\377\377reject Attempt to change key of crypto.", peeraddress);
3392 Con_Printf(
"Datagram_ParseConnectionless: sending \"reject Attempt to downgrade crypto.\" to %s.\n", addressstring2);
3393 NetConn_WriteString(mysocket,
"\377\377\377\377reject Attempt to downgrade crypto.", peeraddress);
3402 Con_Printf(
"Datagram_ParseConnectionless: sending \"accept\" to %s.\n", addressstring2);
3413 Con_Printf(
"Datagram_ParseConnectionless: sending duplicate accept to %s.\n", addressstring2);
3426 for (clientnum = 0; clientnum <
svs.
maxclients; clientnum++)
3437 Con_Printf(
"Datagram_ParseConnectionless: sending \"accept\" to %s.\n", conn->
address);
3450 Con_Printf(
"Datagram_ParseConnectionless: sending \"reject Server is full.\" to %s.\n", addressstring2);
3457 const char *challenge =
NULL;
3463 if (
length > 8 &&
string[7] ==
' ')
3464 challenge =
string + 8;
3469 Con_DPrintf(
"Sending reply to master %s - %s\n", addressstring2, response);
3476 const char *challenge =
NULL;
3482 if (
length > 10 &&
string[9] ==
' ')
3483 challenge =
string + 10;
3488 Con_DPrintf(
"Sending reply to client %s - %s\n", addressstring2, response);
3493 if (
length >= 37 && !memcmp(
string,
"srcon HMAC-MD4 TIME ", 20))
3495 char *password =
string + 20;
3496 char *timeval =
string + 37;
3497 char *s = strchr(timeval,
' ');
3498 char *endpos =
string +
length + 1;
3499 const char *userlevel;
3509 RCon_Execute(mysocket, peeraddress, addressstring2, userlevel, s, endpos,
false);
3512 if (
length >= 42 && !memcmp(
string,
"srcon HMAC-MD4 CHALLENGE ", 25))
3514 char *password =
string + 25;
3515 char *challenge =
string + 42;
3516 char *s = strchr(challenge,
' ');
3517 char *endpos =
string +
length + 1;
3518 const char *userlevel;
3524 RCon_Execute(mysocket, peeraddress, addressstring2, userlevel, s, endpos,
false);
3527 if (
length >= 5 && !memcmp(
string,
"rcon ", 5))
3530 char *s =
string + 5;
3531 char *endpos =
string +
length + 1;
3538 if (j < (
int)
sizeof(password) - 1)
3546 RCon_Execute(mysocket, peeraddress, addressstring2, userlevel, s, endpos,
false);
3550 if (!strncmp(
string,
"extResponse ", 12))
3559 if (!strncmp(
string,
"ping", 4))
3562 Con_DPrintf(
"Received ping from %s, sending ack\n", addressstring2);
3566 if (!strncmp(
string,
"ack", 3))
3581 const char *protocolname;
3594 Con_DPrintf(
"Datagram_ParseConnectionless: received CCREQ_CONNECT from %s.\n", addressstring2);
3616 Con_DPrintf(
"Datagram_ParseConnectionless: sending CCREP_REJECT \"Incompatible version.\" to %s.\n", addressstring2);
3641 Con_Printf(
"Datagram_ParseConnectionless: sending CCREP_REJECT \"Attempt to downgrade crypto.\" to %s.\n", addressstring2);
3655 Con_DPrintf(
"Datagram_ParseConnectionless: sending duplicate CCREP_ACCEPT to %s.\n", addressstring2);
3667 if (knownclient->
begun)
3687 Con_DPrintf(
"Datagram_ParseConnectionless: sending CCREP_ACCEPT to %s.\n", addressstring2);
3705 Con_DPrintf(
"Datagram_ParseConnectionless: sending CCREP_REJECT \"Server is full.\" to %s.\n", addressstring2);
3718 Con_DPrintf(
"Datagram_ParseConnectionless: received CCREQ_SERVER_INFO from %s.\n", addressstring2);
3728 char myaddressstring[128];
3730 Con_DPrintf(
"Datagram_ParseConnectionless: sending CCREP_SERVER_INFO to %s.\n", addressstring2);
3753 Con_DPrintf(
"Datagram_ParseConnectionless: received CCREQ_PLAYER_INFO from %s.\n", addressstring2);
3762 int playerNumber, activeNumber, clientNumber;
3768 if (client->
active && ++activeNumber == playerNumber)
3793 Con_DPrintf(
"Datagram_ParseConnectionless: received CCREQ_RULE_INFO from %s.\n", addressstring2);
3825 Con_DPrintf(
"Datagram_ParseConnectionless: received CCREQ_RCON from %s.\n", addressstring2);
3828 char password[2048];
3832 const char *userlevel;
3838 RCon_Execute(mysocket, peeraddress, addressstring2, userlevel, s, endpos,
true);
3874void NetConn_QueryMasters(
qbool querydp,
qbool queryqw)
3880 char lookupstring[128];
3885 memset(dpmasterstatus, 0,
sizeof(dpmasterstatus));
3886 memset(qwmasterstatus, 0,
sizeof(qwmasterstatus));
3894 const char *cmdname, *extraoptions;
3900 cmdname =
"getserversExt";
3901 extraoptions =
" ipv4 ipv6";
3905 cmdname =
"getservers";
3908 dpsnprintf(request,
sizeof(request),
"\377\377\377\377%s %s %u empty full%s",
3918 if (serverlist_consoleoutput || net_slist_debug.
integer)
3921 Con_Printf(
"Querying DP master %s (resolved from %s)\n", lookupstring,
sv_masters[masternum].
string);
3925 dpmasterstatus[masternum] = MASTER_TX_QUERY;
3930 for(j = 0; j < nFavorites; ++j)
3952 if(sv_qwmasters[masternum].
string[0]
3956 if (serverlist_consoleoutput || net_slist_debug.
integer)
3959 Con_Printf(
"Querying QW master %s (resolved from %s)\n", lookupstring, sv_qwmasters[masternum].
string);
3963 qwmasterstatus[masternum] = MASTER_TX_QUERY;
3968 for(j = 0; j < nFavorites; ++j)
3971 NetConn_ClientParsePacket_ServerList_PrepareQuery(
PROTOCOL_QUAKEWORLD, lookupstring,
true);
3978 Con_Print(
CON_ERROR "Unable to query master servers, no suitable network sockets active.\n");
4013 NetConn_WriteString(mysocket,
"\377\377\377\377heartbeat DarkPlaces\x0A", &masteraddress);
4022 Con_Print(
"No server running, can not heartbeat to master server.\n");
4055 Con_Print(
"Sending new requests to DP master servers\n");
4056 ServerList_QueryList(
false,
true,
false,
true);
4057 Con_Print(
"Listening for replies...\n");
4060 ServerList_QueryList(
false,
true,
false,
false);
4065 ServerList_ResetMasks();
4066 serverlist_sortbyfield = SLIF_PING;
4067 serverlist_sortflags = 0;
4070 Con_Print(
"Sending requests to DP master servers\n");
4071 ServerList_QueryList(
true,
true,
false,
true);
4072 Con_Print(
"Listening for replies...\n");
4075 ServerList_QueryList(
true,
true,
false,
false);
4080 ServerList_ResetMasks();
4081 serverlist_sortbyfield = SLIF_PING;
4082 serverlist_sortflags = 0;
4085 Con_Print(
"Sending requests to QW master servers\n");
4086 ServerList_QueryList(
true,
false,
true,
true);
4087 Con_Print(
"Listening for replies...\n");
4090 ServerList_QueryList(
true,
false,
true,
false);
4103 Cmd_AddCommand(
CF_CLIENT,
"net_slist", Net_Slist_f,
"query dp master servers and print all server information");
4104 Cmd_AddCommand(
CF_CLIENT,
"net_slistqw", Net_SlistQW_f,
"query qw master servers and print all server information");
4105 Cmd_AddCommand(
CF_CLIENT,
"net_refresh", Net_Refresh_f,
"query dp master servers and refresh all server information");
4180 if (
i >= 0 &&
i < 65536)
4182 Con_Printf(
"-port option used, setting port cvar to %i\n",
i);
void CL_ForwardToServer(const char *s)
adds the string as a clc_stringcmd to the client message.
void CL_DisconnectEx(qbool kicked, const char *fmt,...)
void CL_ParseServerMessage(void)
char cl_connect_status[MAX_QPATH]
User-friendly connection status for the menu and/or loading screen, colours and not supported.
void Cmd_AddCommand(unsigned flags, const char *cmd_name, xcommand_t function, const char *description)
called by the init functions of other parts of the program to register commands and functions to call...
cmd_state_t * cmd_local
command interpreter for local commands injected by SVQC, CSQC, MQC, server or client engine code uses...
void Cmd_PreprocessAndExecuteString(cmd_state_t *cmd, const char *text, size_t textlen, cmd_source_t src, qbool lockmutex)
Like Cmd_ExecuteString, but with variable expansion.
@ src_local
from the command buffer
#define CF_NOTIFY
cvar should trigger a chat notification to all connected clients when changed
#define CF_SERVER
cvar/command that only the server can change/execute
#define CF_CLIENT
cvar/command that only the client can change/execute
#define CF_ARCHIVE
cvar should have its set value saved to config.cfg and persist across sessions
#define CF_PRIVATE
cvar should not be $ expanded or sent to the server under any circumstances (rcon_password,...
char com_modname[MAX_OSPATH]
const char * gamenetworkfiltername
#define IS_NEXUIZ_DERIVED(g)
void InfoString_SetValue(char *buffer, size_t bufferlength, const char *key, const char *value)
size_t InfoString_GetValue(const char *buffer, const char *key, char *value, size_t valuesize)
Returns the number of bytes written to *value excluding the \0 terminator.
void MSG_BeginReading(sizebuf_t *sb)
char * MSG_ReadString(sizebuf_t *sb, char *string, size_t maxstring)
void MSG_WriteString(sizebuf_t *sb, const char *s)
void MSG_WriteLong(sizebuf_t *sb, int c)
void MSG_WriteByte(sizebuf_t *sb, int c)
void MSG_WriteUnterminatedString(sizebuf_t *sb, const char *s)
void StoreLittleLong(unsigned char *buffer, unsigned int i)
Encode a little endian 32bit int to the given buffer.
void MSG_WriteChar(sizebuf_t *sb, int c)
void StoreBigLong(unsigned char *buffer, unsigned int i)
Encode a big endian 32bit int to the given buffer.
int BuffBigLong(const unsigned char *buffer)
Extract a big endian 32bit int from the given buffer.
void SZ_Clear(sizebuf_t *buf)
char * dp_ustr2stp(char *dst, size_t dsize, const char *src, size_t slen)
Copies a measured byte sequence (unterminated string) to a null-terminated string.
char com_token[MAX_INPUTLINE]
char * va(char *buf, size_t buflen, const char *format,...)
size_t COM_StringDecolorize(const char *in, size_t size_in, char *out, size_t size_out, qbool escape_carets)
qbool COM_ParseToken_Console(const char **datapointer)
void Com_HexDumpToConsole(const unsigned char *data, int size)
void SZ_HexDumpToConsole(const sizebuf_t *buf)
void SZ_Write(sizebuf_t *buf, const unsigned char *data, int length)
int dpsnprintf(char *buffer, size_t buffersize, const char *format,...)
Returns the number of printed characters, excluding the final '\0' or returns -1 if the buffer isn't ...
size_t base64_encode(unsigned char *buf, size_t buflen, size_t outbuflen)
@ PROTOCOL_DARKPLACES2
various changes
@ PROTOCOL_NEHAHRABJP2
same as NEHAHRABJP but with 16bit soundindex
@ PROTOCOL_DARKPLACES3
uses EntityFrame4 entity snapshot encoder/decoder which is broken, this attempted to do partial snaps...
@ PROTOCOL_NEHAHRABJP
same as QUAKEDP but with 16bit modelindex
@ PROTOCOL_DARKPLACES7
added QuakeWorld-style movement protocol to allow more consistent prediction
@ PROTOCOL_QUAKEDP
darkplaces extended quake protocol (used by TomazQuake and others), backwards compatible as long as n...
@ PROTOCOL_QUAKE
quake (aka netquake/normalquake/nq) protocol
@ PROTOCOL_NEHAHRABJP3
same as NEHAHRABJP2 but with some changes
@ PROTOCOL_NEHAHRAMOVIE
Nehahra movie protocol, a big nasty hack dating back to early days of the Quake Standards Group (but ...
@ PROTOCOL_QUAKEWORLD
quakeworld protocol
@ PROTOCOL_DARKPLACES1
uses EntityFrame entity snapshot encoder/decoder which is a QuakeWorld-like entity snapshot delta com...
#define dp_strlcpy(dst, src, dsize)
void Con_Print(const char *msg)
Prints to all appropriate console targets, and adds timestamps.
void Con_DPrintf(const char *fmt,...)
A Con_Printf that only shows up if the "developer" cvar is set.
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
void Con_Rcon_Redirect_Init(lhnetsocket_t *sock, lhnetaddress_t *dest, qbool proquakeprotocol)
void Con_DPrint(const char *msg)
A Con_Print that only shows up if the "developer" cvar is set.
void Con_Rcon_Redirect_End(void)
crypto_t * Crypto_ServerGetInstance(lhnetaddress_t *peeraddress)
void Crypto_LoadKeys(void)
int crypto_keyfp_recommended_length
int Crypto_ClientParsePacket(const char *data_in, size_t len_in, char *data_out, size_t *len_out, lhnetaddress_t *peeraddress, const char *peeraddressstring)
const void * Crypto_EncryptPacket(crypto_t *crypto, const void *data_src, size_t len_src, void *data_dst, size_t *len_dst, size_t len)
qbool Crypto_RetrieveHostKey(lhnetaddress_t *peeraddress, int *keyid, char *keyfp, size_t keyfplen, char *idfp, size_t idfplen, int *aeslevel, qbool *issigned)
const void * Crypto_DecryptPacket(crypto_t *crypto, const void *data_src, size_t len_src, void *data_dst, size_t *len_dst, size_t len)
static const char * crypto_idstring
int Crypto_ServerParsePacket(const char *data_in, size_t len_in, char *data_out, size_t *len_out, lhnetaddress_t *peeraddress)
const char * Crypto_GetInfoResponseDataString(void)
qbool Crypto_ServerAppendToChallenge(const char *data_in, size_t len_in, char *data_out, size_t *len_out, size_t maxlen_out)
qbool Crypto_FinishInstance(crypto_t *out, crypto_t *crypto)
#define CRYPTO_HEADERSIZE
#define ENCRYPTION_REQUIRED
void Cvar_SetValueQuick(cvar_t *var, float value)
void Cvar_SetQuick(cvar_t *var, const char *value)
void Cvar_RegisterVariable(cvar_t *variable)
registers a cvar that already has the name, string, and optionally the archive elements set.
void Cvar_RegisterVirtual(cvar_t *variable, const char *name)
cvar_t * Cvar_FindVarAfter(cvar_state_t *cvars, const char *prev_var_name, unsigned neededflags)
void Cvar_RegisterCallback(cvar_t *variable, void(*callback)(cvar_t *))
int matchpattern_with_separator(const char *in, const char *pattern, int caseinsensitive, const char *separators, qbool wildcard_least_one)
static int(ZEXPORT *qz_inflate)(z_stream *strm
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
GLsizei const GLchar ** string
GLenum GLuint GLenum GLsizei length
GLenum GLenum GLsizei count
GLsizeiptr const GLvoid * data
GLenum GLuint GLenum GLsizei const GLchar * buf
#define HMAC_MDFOUR_16BYTES(out, in, n, key, k)
void Host_Error(const char *error,...)
int LHNETADDRESS_SetPort(lhnetaddress_t *vaddress, int port)
int LHNETADDRESS_FromPort(lhnetaddress_t *vaddress, lhnetaddresstype_t addresstype, int port)
int LHNETADDRESS_ToString(const lhnetaddress_t *vaddress, char *string, int stringbuffersize, int includeport)
Returns the number of bytes written to *string excluding the \0 terminator.
int LHNET_Write(lhnetsocket_t *lhnetsocket, const void *content, int contentlength, const lhnetaddress_t *vaddress)
const char * LHNETADDRESS_GetInterfaceName(const lhnetaddress_t *vaddress, char *ifname, size_t ifnamelength)
void LHNET_CloseSocket(lhnetsocket_t *lhnetsocket)
void LHNET_Shutdown(void)
int LHNET_DefaultDSCP(int dscp)
lhnetsocket_t * LHNET_OpenSocket_Connectionless(lhnetaddress_t *address)
int LHNETADDRESS_FromString(lhnetaddress_t *vaddress, const char *string, int defaultport)
int LHNET_Read(lhnetsocket_t *lhnetsocket, void *content, int maxcontentlength, lhnetaddress_t *vaddress)
lhnetaddress_t * LHNET_AddressFromSocket(lhnetsocket_t *sock)
int LHNETADDRESS_GetPort(const lhnetaddress_t *address)
int LHNETADDRESS_Compare(const lhnetaddress_t *vaddress1, const lhnetaddress_t *vaddress2)
static lhnetaddresstype_t LHNETADDRESS_GetAddressType(const lhnetaddress_t *address)
#define bound(min, num, max)
static void RCon_Execute(lhnetsocket_t *mysocket, lhnetaddress_t *peeraddress, const char *addressstring2, const char *userlevel, const char *s, const char *endpos, qbool proquakeprotocol)
static lhnetsocket_t * cl_sockets[16]
static void NetConn_OpenClientPort(const char *addressstring, lhnetaddresstype_t addresstype, int defaultport)
netconn_t * NetConn_Open(lhnetsocket_t *mysocket, lhnetaddress_t *peeraddress)
mempool_t * netconn_mempool
void NetConn_Heartbeat(int priority)
static qbool NetConn_BuildStatusResponse(const char *challenge, char *out_msg, size_t out_size, qbool fullstatus)
(div0) build the full response only if possible; better a getinfo response than no response at all if...
cvar_t net_messagetimeout
unsigned cl_net_extresponse_last
qbool NetConn_CanSend(netconn_t *conn)
static cvar_t sv_masters[]
int NetConn_Write(lhnetsocket_t *mysocket, const void *data, int length, const lhnetaddress_t *peeraddress)
static double nextheartbeattime
static cvar_t sv_heartbeatperiod
int NetConn_WriteString(lhnetsocket_t *mysocket, const char *string, const lhnetaddress_t *peeraddress)
void Net_Stats_f(cmd_state_t *cmd)
static int NetConn_ReceivedMessage(netconn_t *conn, const unsigned char *data, size_t length, protocolversion_t protocol, double newtimeout)
int NetConn_Read(lhnetsocket_t *mysocket, void *data, int maxlength, lhnetaddress_t *peeraddress)
unsigned serverquerycount
unsigned sv_net_extresponse_count
char sv_net_extresponse[NET_EXTRESPONSE_MAX][1400]
lhnetsocket_t * NetConn_ChooseClientSocketForAddress(lhnetaddress_t *address)
static void NetConn_CL_UpdateSockets_Callback(cvar_t *var)
cvar_t net_connecttimeout
static unsigned cl_numsockets
static qbool hmac_mdfour_challenge_matching(lhnetaddress_t *peeraddress, const char *password, const char *hash, const char *s, int slen)
static unsigned sv_numsockets
static cvar_t rcon_restricted_commands
static cvar_t gameversion_min
void NetConn_UpdateSockets(void)
unsigned sv_net_extresponse_last
cvar_t sv_public_rejectreason
static cvar_t net_tos_dscp
challenge_t challenges[MAX_CHALLENGES]
char cl_readstring[MAX_INPUTLINE]
char sv_readstring[MAX_INPUTLINE]
static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *data, int length, lhnetaddress_t *peeraddress)
static lhnetsocket_t * sv_sockets[16]
qbool NetConn_HaveServerPorts(void)
cvar_t developer_networking
void NetConn_ClientFrame(void)
static void NetConn_BuildChallengeString(char *buffer, int bufferlength)
static void NetConn_UpdateCleartime(double *cleartime, int rate, int burstsize, int len)
static cvar_t net_fakeloss_receive
static unsigned char cl_message_buf[NET_MAXMESSAGE]
cvar_t rcon_secure_challengetimeout
lhnetsocket_t * NetConn_ChooseServerSocketForAddress(lhnetaddress_t *address)
unsigned cl_net_extresponse_count
static void Net_Heartbeat_f(cmd_state_t *cmd)
unsigned masterquerycount
qbool(* rcon_matchfunc_t)(lhnetaddress_t *peeraddress, const char *password, const char *hash, const char *s, int slen)
qbool NetConn_HaveClientPorts(void)
void NetConn_Close(netconn_t *conn)
static cvar_t rcon_restricted_password
cvar_t net_challengefloodblockingtimeout
cvar_t net_getstatusfloodblockingtimeout
int NetConn_IsLocalGame(void)
static qbool hmac_mdfour_time_matching(lhnetaddress_t *peeraddress, const char *password, const char *hash, const char *s, int slen)
static cvar_t gameversion
static unsigned char sv_message_buf[NET_MAXMESSAGE]
static qbool NetConn_PreventFlood(lhnetaddress_t *peeraddress, server_floodaddress_t *floodlist, size_t floodlength, double floodtime, qbool renew)
void NetConn_ServerFrame(void)
void NetConn_Shutdown(void)
void NetConn_OpenServerPorts(int opennetports)
char cl_net_extresponse[NET_EXTRESPONSE_MAX][1400]
unsigned serverreplycount
void NetConn_OpenClientPorts(void)
static int NetConn_AddCryptoFlag(crypto_t *crypto)
void NetConn_CloseServerPorts(void)
int NetConn_SendUnreliableMessage(netconn_t *conn, sizebuf_t *data, protocolversion_t protocol, int rate, int burstsize, qbool quakesignon_suppressreliables)
unsigned masterreplycount
static qbool plaintext_matching(lhnetaddress_t *peeraddress, const char *password, const char *hash, const char *s, int slen)
void NetConn_ClearFlood(lhnetaddress_t *peeraddress, server_floodaddress_t *floodlist, size_t floodlength)
static void NetConn_sv_netport_Callback(cvar_t *var)
cvar_t net_connect_entnum_ofs
cvar_t net_sourceaddresscheck
static cvar_t gameversion_max
static void PrintStats(netconn_t *conn)
static const char * RCon_Authenticate(lhnetaddress_t *peeraddress, const char *password, const char *s, const char *endpos, rcon_matchfunc_t comparator, const char *cs, int cslen)
returns a string describing the user level, or NULL for auth failure
static void NetConn_ConnectionEstablished(lhnetsocket_t *mysocket, lhnetaddress_t *peeraddress, protocolversion_t initialprotocol)
static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *data, int length, lhnetaddress_t *peeraddress)
uint8_t serverlist_querystage
bitfield because in theory we could be doing QW & DP simultaneously
static cvar_t rcon_secure_maxdiff
static cvar_t net_fakeloss_send
void NetConn_CloseClientPorts(void)
cvar_t net_connectfloodblockingtimeout
static qbool NetConn_OpenServerPort(const char *addressstring, lhnetaddresstype_t addresstype, int defaultport, int range)
#define CCREP_SERVER_INFO
#define NETGRAPH_NOPACKET
#define CCREP_PLAYER_INFO
#define NET_EXTRESPONSE_MAX
#define NETFLAG_UNRELIABLE
#define NETGRAPH_CHOKEDPACKET
#define CCREQ_PLAYER_INFO
#define NET_PROTOCOL_VERSION
#define NETFLAG_LENGTH_MASK
#define CCREQ_SERVER_INFO
#define NETGRAPH_LOSTPACKET
#define PRVM_EDICT_NUM(n)
const char * PRVM_GetString(prvm_prog_t *prog, int num)
#define PRVM_serverglobalstring(fieldname)
#define PRVM_serveredictstring(ed, fieldname)
void Protocol_Names(char *buffer, size_t buffersize)
#define MAX_INPUTLINE
maximum size of console commandline, QuakeC strings, and many other text processing buffers
#define SERVERLIST_ANDMASKCOUNT
max items in server list AND mask
#define NET_MAXMESSAGE
max reliable packet size (sent as multiple fragments of MAX_PACKETFRAGMENT)
#define SERVERLIST_TOTALSIZE
max servers in the server list
#define MAX_FAVORITESERVERS
#define SERVERLIST_ORMASKCOUNT
max items in server list OR mask
#define MAX_PACKETFRAGMENT
max length of packet fragment
void SV_ReadClientMessage(void)
#define SV_LockThreadMutex()
void SV_SendServerinfo(client_t *client)
#define SV_UnlockThreadMutex()
server_static_t svs
persistant server info
void SV_ConnectClient(int clientnum, netconn_t *netconnection)
unsigned int servermovesequence
char connect_userinfo[MAX_USERINFO_STRING]
int connect_remainingtries
int proquake_serverversion
lhnetaddress_t rcon_addresses[MAX_RCONS]
double rcon_timeout[MAX_RCONS]
unsigned int qw_outgoing_sequence
unsigned int qw_incoming_sequence
lhnetaddress_t rcon_address
double connect_nextsendtime
lhnetaddress_t connect_address
lhnetsocket_t * connect_mysocket
char rcon_commands[MAX_RCONS][MAX_INPUTLINE]
protocolversion_t protocol
char userinfo[MAX_USERINFO_STRING]
qbool active
false = empty client slot
qbool begun
false = don't send datagrams
char name[MAX_SCOREBOARDNAME]
netconn_t * netconnection
communications handle
double connecttime
realtime this client connected
float ping
LadyHavoc: can be used for prediction or whatever...
command interpreter state - the tokenizing and execution of commands, as well as pointers to which cv...
char server_keyfp[FP64_SIZE+1]
char client_idfp[FP64_SIZE+1]
char client_keyfp[FP64_SIZE+1]
char server_idfp[FP64_SIZE+1]
double dirtytime
the main loop wall time for this frame, equal to Sys_DirtyTime() at the start of this host frame
double realtime
the accumulated mainloop time since application started (with filtering), without any slowmo or clamp...
lhnetaddresstype_t addresstype
unsigned int sendSequence
unsigned int unreliableReceiveSequence
unsigned int receiveSequence
unsigned int last_reliable_sequence
sequence number of last send
qbool incoming_reliable_sequence
single bit, maintained local
unsigned int incoming_acknowledged
qbool incoming_reliable_acknowledged
single bit
unsigned int incoming_sequence
qbool reliable_sequence
single bit
int incoming_packetcounter
int reliableMessagesReceived
int outgoing_packetcounter
netgraphitem_t incoming_netgraph[NETGRAPH_PACKETS]
int receiveMessageLength
reliable message that is currently being received (for putting together fragments)
int unreliableMessagesReceived
lhnetaddress_t peeraddress
unsigned char messagedata[NET_MAXMESSAGE]
unsigned char receiveMessage[NET_MAXMESSAGE]
unsigned int outgoing_unreliable_sequence
used by both NQ and QW protocols
int unreliableMessagesSent
double incoming_cleartime
int sendMessageLength
reliable message that is currently sending (for building fragments)
sizebuf_t message
writing buffer to send to peer as the next reliable message can be added to at any time,...
unsigned char sendMessage[NET_MAXMESSAGE]
struct netconn_t::netconn_qw_s qw
int receivedDuplicateCount
netgraphitem_t outgoing_netgraph[NETGRAPH_PACKETS]
struct netconn_t::netconn_nq_s nq
struct client_s * clients
client slots
int maxclients
number of svs.clients slots (updated by maxplayers command)
char worldbasename[MAX_QPATH]
qbool active
false if only a net client
server_floodaddress_t connectfloodaddresses[MAX_CONNECTFLOODADDRESSES]
connection flood blocking note this is in server_t rather than server_static_t so that it is reset on...
server_floodaddress_t getstatusfloodaddresses[MAX_GETSTATUSFLOODADDRESSES]
protocolversion_t protocol
one of the PROTOCOL_ values
qbool overflowed
set to true if the buffer size failed
double Sys_DirtyTime(void)
int Sys_CheckParm(const char *parm)
#define Thread_DestroyMutex(m)
qbool Thread_HasThreads(void)
#define Thread_CreateMutex()
#define Thread_LockMutex(m)
#define Thread_UnlockMutex(m)
#define Mem_Alloc(pool, size)
#define Mem_AllocPool(name, flags, parent)
#define Mem_Realloc(pool, data, size)