Quake II RTX doxygen
1.0 dev
|
|
Go to the documentation of this file.
108 char hashlist_name[MAX_QPATH];
111 #define ACP_BLOCKPLAY (1 << 0)
113 #define ACH_REQUIRED (1 << 0)
114 #define ACH_NEGATIVE (1 << 1)
116 #define AC_PROTOCOL_VERSION 0xAC03
118 #define AC_DEFAULT_BACKOFF 30
120 #define AC_PING_INTERVAL 60000
121 #define AC_PING_TIMEOUT 15000
123 #define AC_MESSAGE "\220\xe1\xee\xf4\xe9\xe3\xe8\xe5\xe1\xf4\221 "
125 #define AC_SEND_SIZE 131072
126 #define AC_RECV_SIZE 1024
168 #define AC_HASHES_NAME "anticheat-hashes.txt"
169 #define AC_CVARS_NAME "anticheat-cvars.txt"
170 #define AC_TOKENS_NAME "anticheat-tokens.txt"
172 #define AC_MAX_INCLUDES 16
226 size_t pathlen, hashlen;
239 Com_WPrintf(
"ANTICHEAT: Incomplete line %d in %s\n", linenum, path);
244 if (pathlen < 1 || pathlen >= MAX_QPATH) {
245 Com_WPrintf(
"ANTICHEAT: Invalid quake path length on line %d in %s\n", linenum, path);
248 if (strchr(pstr,
'\\') || !Q_isalnum(pstr[0])) {
249 Com_WPrintf(
"ANTICHEAT: Malformed quake path on line %d in %s\n", linenum, path);
255 Com_WPrintf(
"ANTICHEAT: Malformed hash on line %d in %s\n", linenum, path);
259 for (i = 0; i < 20; i++, hstr += 2) {
260 int c1 = Q_charhex(hstr[0]);
261 int c2 = Q_charhex(hstr[1]);
262 if (c1 == -1 || c2 == -1) {
265 hash[i] = (c1 << 4) | c2;
271 if (strstr(data,
"required")) {
274 if (strstr(data,
"negative")) {
279 file =
SV_Malloc(
sizeof(*file) + pathlen);
280 memcpy(file->
hash, hash,
sizeof(file->
hash));
281 memcpy(file->
path, pstr, pathlen + 1);
290 char *values[256], *p;
292 char *name, *opstr, *val, *def;
293 size_t len, namelen, vallen, deflen;
300 Com_WPrintf(
"ANTICHEAT: Incomplete line %d in %s\n", linenum, path);
305 Com_WPrintf(
"ANTICHEAT: Incomplete line %d in %s\n", linenum, path);
310 Com_WPrintf(
"ANTICHEAT: Incomplete line %d in %s\n", linenum, path);
315 if (namelen < 1 || namelen >= 64) {
316 Com_WPrintf(
"ANTICHEAT: Invalid cvar name length on line %d in %s\n", linenum, path);
319 if (deflen < 1 || deflen >= 64) {
320 Com_WPrintf(
"ANTICHEAT: Invalid default value length on line %d in %s\n", linenum, path);
325 if (!strcmp(opstr, op->
str)) {
330 Com_WPrintf(
"ANTICHEAT: Unknown opcode '%s' on line %d in %s\n", opstr, linenum, path);
337 Com_WPrintf(
"ANTICHEAT: Too many values for opcode '%s' on line %d in %s\n", opstr, linenum, path);
341 Com_WPrintf(
"ANTICHEAT: Empty value on line %d in %s\n", linenum, path);
344 p = strchr(val,
',');
350 Com_WPrintf(
"ANTICHEAT: Too long value on line %d in %s\n", linenum, path);
353 values[num_values] = val;
354 lengths[num_values++] = (byte)(len + 1);
361 Z_TagReserve(
sizeof(*cvar) + num_values *
sizeof(
char *) +
362 namelen + 1 + deflen + 1 + vallen + 1, TAG_SERVER);
366 memcpy(cvar->
name, name, namelen + 1);
368 memcpy(cvar->
def, def, deflen + 1);
370 for (i = 0; i < num_values; i++) {
372 memcpy(cvar->
values[i], values[i], lengths[i]);
383 size_t len = strlen(data);
386 memcpy(tok->string, data, len + 1);
393 char *raw, *data, *p;
397 ret = FS_LoadFile(path, (
void **)&raw);
399 if (ret != Q_ERR_NOENT || depth) {
400 Com_WPrintf(
"ANTICHEAT: Could not %s %s: %s\n",
408 p = strchr(data,
'\n');
410 if (p > data && *(p - 1) ==
'\r') {
422 if (!strncmp(data + 1,
"include ", 8)) {
424 Com_WPrintf(
"ANTICHEAT: Includes too deeply nested.\n");
429 Com_WPrintf(
"ANTICHEAT: Unknown directive %s on line %d in %s\n", data + 1, linenum, path);
433 parse(data, linenum, path);
454 "not using any file checks.\n");
457 Com_Printf(
"ANTICHEAT: No file hashes were loaded, "
467 "not using any cvar checks.\n");
469 Com_Printf(
"ANTICHEAT: No cvar checks were loaded, "
480 string_entry_t *t, *tn;
519 Com_Printf(
"ANTICHEAT: Re%s in %s.\n",
532 Com_Printf(
"ANTICHEAT: Server connection failed.\n");
539 cl->ac_valid = qfalse;
540 cl->ac_file_failures = 0;
546 "This server has lost the connection to the anticheat server. "
547 "Any anticheat clients are no longer valid.\n");
551 "You will need to reconnect once the server has "
552 "re-established the anticheat connection.\n");
559 Com_WPrintf(
"ANTICHEAT: Lost connection to anticheat server!\n");
562 memset(&
ac, 0,
sizeof(
ac));
574 char string[MAX_STRING_CHARS];
577 va_start(argptr, fmt);
578 len =
Q_vsnprintf(
string,
sizeof(
string), fmt, argptr);
581 if (len >=
sizeof(
string)) {
582 Com_WPrintf(
"%s: overflow\n", __func__);
589 MSG_WriteData(
string, len + 1);
611 Com_DPrintf(
"ANTICHEAT: Message too short in %s\n", __func__);
619 Com_WPrintf(
"ANTICHEAT: Illegal client ID: %u\n", clientID);
627 if (
cl->challenge != challenge) {
642 char clientreason[64];
650 Com_DPrintf(
"ANTICHEAT: Message too short in %s\n", __func__);
669 if (strcmp(reason,
"disconnected")) {
673 Q_snprintf(showreason,
sizeof(showreason),
" (%s)", reason);
678 cl->name, showreason);
680 Com_Printf(
"ANTICHEAT VIOLATION: %s[%s] was kicked: %s\n",
696 Com_Printf(
"ANTICHEAT DISCONNECT: %s[%s] disconnected from "
697 "anticheat server\n",
cl->name,
701 AC_Announce(
cl,
"%s lost connection to anticheat server.\n",
cl->name);
707 "client is no longer valid.\n",
cl->name);
708 cl->ac_valid = qfalse;
721 Com_DPrintf(
"ANTICHEAT: Message too short in %s\n", __func__);
726 Com_DPrintf(
"ANTICHEAT: %s with client in state %d\n",
727 __func__,
cl->state);
731 Com_DPrintf(
"ANTICHEAT: %s for %s\n", __func__,
cl->name);
733 cl->ac_valid = qtrue;
740 char path[MAX_QPATH];
741 char hash[MAX_QPATH];
752 Com_DPrintf(
"ANTICHEAT: Message too short in %s\n", __func__);
757 if (pathlen >=
sizeof(path)) {
758 Com_WPrintf(
"ANTICHEAT: Oversize path in %s\n", __func__);
759 pathlen =
sizeof(path) - 1;
765 strcpy(hash,
"no hash?");
768 cl->ac_file_failures++;
772 if (!strcmp(f->
path, path)) {
780 Com_Printf(
"ANTICHEAT FILE VIOLATION: %s[%s] has a modified %s [%s]\n",
788 "Your file %s has been modified. "
789 "Please replace it with a known valid copy.\n", path);
808 AC_Announce(
cl,
"%s was kicked for too many modified files\n",
cl->name);
814 memcpy(bad->string, path, pathlen + 1);
815 bad->next =
cl->ac_bad_files;
816 cl->ac_bad_files = bad;
824 Com_Printf(
"ANTICHEAT: Ready to serve anticheat clients.\n");
826 CVAR_SERVERINFO | CVAR_ROM, FROM_CODE);
840 Com_DPrintf(
"ANTICHEAT: Message too short in %s\n", __func__);
847 cl->ac_query_sent = AC_QUERY_DONE;
849 cl->ac_client_type = type;
850 cl->ac_valid = qtrue;
854 Com_WPrintf(
"ANTICHEAT: %s with client in state %d\n",
855 __func__,
cl->state);
860 Com_DPrintf(
"ANTICHEAT: %s for %s\n", __func__,
cl->name);
881 Com_Printf(
"ANTICHEAT: Dropping %s, disconnect message.\n",
cl->name);
888 char string[MAX_STRING_CHARS];
891 Com_EPrintf(
"ANTICHEAT: %s\n",
string);
902 if (!FIFO_TryRead(&
ac.
stream.recv, &msglen, 2)) {
908 msglen = LittleShort(msglen);
910 Com_EPrintf(
"ANTICHEAT: Oversize message: %u bytes\n", msglen);
945 Com_WPrintf(
"ANTICHEAT: You do not have permission to "
946 "use the anticheat server. Anticheat disabled.\n");
950 Com_WPrintf(
"ANTICHEAT: The anticheat server is no longer "
951 "compatible with this version of " APPLICATION
". "
952 "Please make sure you are using the latest " APPLICATION
" version. "
953 "Anticheat disabled.\n");
964 Com_EPrintf(
"ANTICHEAT: Unknown command byte %d, please make "
965 "sure you are using the latest " APPLICATION
" version. "
966 "Anticheat disabled.\n", cmd);
972 Com_WPrintf(
"ANTICHEAT: Read %"PRIz
" bytes past end of message %d\n",
994 if (!FIFO_TryWrite(&
ac.
stream.send, src, len)) {
995 Com_WPrintf(
"ANTICHEAT: Send buffer exceeded in %s\n", func);
1004 cl->ac_query_sent = AC_QUERY_SENT;
1026 if (
cl->ac_required == AC_EXEMPT) {
1034 if (
cl->ac_query_sent == AC_QUERY_UNSENT &&
ac.
ready) {
1039 if (
cl->ac_required != AC_REQUIRED) {
1046 Com_Printf(
"ANTICHEAT: Rejected connecting client %s[%s], "
1047 "no anticheat response.\n",
cl->name,
1060 Com_Printf(
"ANTICHEAT: Rejected connecting client %s[%s], "
1061 "no connection to anticheat server.\n",
cl->name,
1064 "This server is unable to take new connections right now. "
1065 "Please try again later.\n");
1078 if (
cl->ac_required == AC_EXEMPT) {
1080 "%s is exempt from using anticheat.\n",
cl->name);
1081 }
else if (
cl->ac_valid) {
1082 if (
cl->ac_file_failures) {
1084 "%s failed %d file check%s.\n",
1085 cl->name,
cl->ac_file_failures,
1086 cl->ac_file_failures == 1 ?
"" :
"s");
1090 "%s is not using anticheat.\n",
cl->name);
1101 cl->ac_required = AC_EXEMPT;
1107 cl->ac_required = AC_REQUIRED;
1109 cl->ac_required = AC_NORMAL;
1111 cl->ac_required = AC_REQUIRED;
1130 cl->ac_query_sent = AC_QUERY_UNSENT;
1131 cl->ac_valid = qfalse;
1145 string_entry_t *tok;
1152 for (tok =
acs.
tokens; tok; tok = tok->next) {
1153 if (!strcmp(tok->string, token)) {
1164 if (
other->ac_token == tok->string) {
1170 "ANTICHEAT: %s bypassed anticheat requirements with token '%s'\n",
1171 cl->name, tok->string);
1172 cl->ac_token = tok->string;
1173 cl->ac_required = AC_EXEMPT;
1218 Com_WPrintf(
"ANTICHEAT: Send buffer length exceeded, "
1219 "server may be frozen for a short while!\n");
1233 size_t len = strlen(s);
1240 MSG_WriteData(s, len);
1256 MSG_WriteData(f->
hash,
sizeof(f->
hash));
1258 if (p && !strcmp(f->
path, p->
path)) {
1270 for (i = 0; i <
c->num_values; i++) {
1329 Com_Printf(
"ANTICHEAT: Server ping timeout, disconnecting.\n");
1343 if (
cl->ac_query_sent != AC_QUERY_SENT) {
1347 Com_WPrintf(
"ANTICHEAT: Query timed out for %s, possible network problem.\n",
cl->name);
1348 cl->ac_valid = qfalse;
1363 Com_WPrintf(
"ANTICHEAT: Unable to lookup %s.\n",
1369 Com_EPrintf(
"ANTICHEAT: %s to %s.\n",
1390 neterr_t ret = NET_AGAIN;
1396 Com_Printf(
"ANTICHEAT: Attempting to reconnect to anticheat server...\n");
1408 if (ret == NET_OK) {
1409 Com_Printf(
"ANTICHEAT: Connected to anticheat server!\n");
1417 if (ret == NET_OK) {
1447 Com_Printf(
"ANTICHEAT: Only supported on dedicated servers, disabling.\n");
1453 Com_Printf(
"ANTICHEAT: Only supported on game servers, disabling.\n");
1460 Com_Printf(
"ANTICHEAT: Attempting to connect to %s...\n",
ac_server_address->string);
1469 for (attempts = 0; attempts < 50; attempts++) {
1476 Com_WPrintf(
"ANTICHEAT: Still not ready, resuming server initialization.\n");
1485 memset(&
ac, 0,
sizeof(
ac));
1486 memset(&
acs, 0,
sizeof(
acs));
1497 Com_Printf(
"No server running.\n");
1502 Com_Printf(
"The anticheat module is not in use on this server.\n"
1503 "For information on anticheat, please visit http://antiche.at/\n");
1510 "+----------------+--------+-----+------+\n"
1511 "| Player Name |AC Valid|Files|Client|\n"
1512 "+----------------+--------+-----+------+\n");
1519 if (*sub && !strstr(
cl->name, sub)) {
1523 if (
cl->ac_required == AC_EXEMPT) {
1524 Com_Printf(
"|%-16s| exempt | N/A | N/A |\n",
cl->name);
1525 }
else if (
cl->ac_valid) {
1526 i =
cl->ac_client_type;
1530 Com_Printf(
"|%-16s| yes | %3d |%-6s|\n",
cl->name,
1533 Com_Printf(
"|%-16s| NO | N/A | N/A |\n",
cl->name);
1537 Com_Printf(
"+----------------+--------+-----+------+\n");
1544 "This Quake II server is %sconnected to the anticheat server.\n"
1545 "For information on anticheat, please visit http://antiche.at/\n",
1552 string_entry_t *bad;
1553 char *substring, *filesubstring;
1557 Com_Printf(
"No server running.\n");
1562 Com_Printf(
"The anticheat module is not in use on this server.\n"
1563 "For information on anticheat, please visit http://antiche.at/\n");
1569 Com_Printf(
"Usage: %s [substring|id] [filesubstring]\n",
Cmd_Argv(0));
1579 clientID = atoi(substring);
1581 Com_Printf(
"Invalid client ID.\n");
1586 Com_Printf(
"Player is not active.\n");
1594 if (strstr(
cl->name, substring)) {
1598 Com_Printf(
"Player not found.\n");
1604 if (!
cl->ac_valid) {
1605 Com_Printf(
"%s is not using anticheat.\n",
cl->name);
1609 if (
cl->ac_bad_files) {
1610 Com_Printf(
"File check failures for %s:\n",
cl->name);
1611 for (bad =
cl->ac_bad_files; bad; bad = bad->next) {
1612 if (!filesubstring[0] || strstr(bad->string, filesubstring)) {
1613 Com_Printf(
"%s\n", bad->string);
1617 Com_Printf(
"%s has no file check failures.\n",
cl->name);
1626 Com_Printf(
"No server running.\n");
1630 Com_Printf(
"Anticheat is not ready.\n");
1640 Com_Printf(
"All clients marked as invalid.\n");
1648 Com_Printf(
"No server running.\n");
1652 Com_Printf(
"Anticheat is not in use.\n");
1665 cl->ac_token = NULL;
1668 Com_Printf(
"Anticheat configuration updated.\n");
1727 "This server requires the r1ch.net anticheat module. "
1728 "Please see http://antiche.at/ for more details.", 0);
static void AC_FreeChecks(void)
void * Z_ReservedAlloc(size_t size)
void SV_DelMatch_f(list_t *list)
static void AC_ListRequirements_f(void)
static void AC_ListExceptions_f(void)
static void AC_Write(const char *func)
static qboolean AC_Reconnect(void)
static void AC_ParseFileViolation(void)
static void AC_LoadChecks(void)
neterr_t NET_Connect(const netadr_t *peer, netstream_t *s)
static cvar_t * ac_required
char * NET_AdrToString(const netadr_t *a)
static void AC_WriteString(const char *s)
static void AC_Disable(void)
char hashlist_name[MAX_QPATH]
size_t Com_FormatTimeLong(char *buffer, size_t size, time_t t)
size_t Q_snprintf(char *dest, size_t size, const char *fmt,...)
static void AC_ParseHash(char *data, int linenum, const char *path)
struct ac_cvar_s ac_cvar_t
qboolean FIFO_ReadMessage(fifo_t *fifo, size_t msglen)
static LIST_DECL(ac_required_list)
static void AC_AddRequirement_f(void)
cvar_t * Cvar_Get(const char *var_name, const char *var_value, int flags)
const char * Q_ErrorString(qerror_t error)
#define AC_DEFAULT_BACKOFF
static void AC_AddException_f(void)
void AC_ClientToken(client_t *cl, const char *token)
static void AC_ParseQueryReply(void)
static void AC_CheckTimeouts(void)
void NET_UpdateStream(netstream_t *s)
static void AC_Drop(void)
static qboolean AC_Flush(void)
neterr_t NET_RunConnect(netstream_t *s)
static cvar_t * ac_server_address
static void AC_Retry(void)
void NET_CloseStream(netstream_t *s)
size_t Q_vsnprintf(char *dest, size_t size, const char *fmt, va_list argptr)
static cvar_t * ac_disable_play
void SV_ListMatches_f(list_t *list)
static void AC_ParseViolation(void)
void MSG_WriteByte(int c)
static qboolean AC_ParseMessage(void)
static void AC_ParseReady(void)
void SV_ClientAddMessage(client_t *client, int flags)
static void AC_Update_f(void)
char * Q_strchrnul(const char *s, int c)
#define FOR_EACH_CLIENT(client)
static void AC_DelException_f(void)
char * AC_ClientConnect(client_t *cl)
static qboolean AC_ParseFile(const char *path, ac_parse_t parse, int depth)
void AC_ClientAnnounce(client_t *cl)
static cvar_t * ac_badfile_action
void AC_Connect(unsigned mvd_spawn)
const char * NET_ErrorString(void)
qboolean AC_ClientBegin(client_t *cl)
#define AC_PROTOCOL_VERSION
static cvar_t * ac_message
void Cmd_Register(const cmdreg_t *reg)
static void AC_ParseError(void)
qboolean NET_StringToAdr(const char *s, netadr_t *a, int default_port)
void(* ac_parse_t)(char *, int, const char *)
void(APIENTRY *qwglDrawBuffer)(GLenum mode)
void Cvar_SetByVar(cvar_t *var, const char *value, from_t from)
static void AC_ParseDisconnect(void)
size_t Q_strlcpy(char *dst, const char *src, size_t size)
static void AC_SendPing(void)
void MSG_WriteShort(int c)
void SV_DropClient(client_t *client, const char *reason)
cvar_t * Cvar_FullSet(const char *var_name, const char *value, int flags, from_t from)
void Z_TagReserve(size_t size, memtag_t tag)
qboolean COM_IsUint(const char *s)
void SV_BroadcastPrintf(int level, const char *fmt,...)
static cvar_t * ac_error_action
static char * AC_SimpleParse(char **data_p, size_t *len_p)
void MSG_WriteLong(int c)
static cvar_t * ac_badfile_message
static void AC_Invalidate_f(void)
static void AC_ClientQuery(client_t *cl)
size_t MSG_ReadString(char *dest, size_t size)
static const int ac_num_clients
static byte ac_recv_buffer[AC_RECV_SIZE]
static void AC_Announce(client_t *client, const char *fmt,...)
static cvar_t * ac_badfile_max
void SV_ClientPrintf(client_t *client, int level, const char *fmt,...)
static const char ac_clients[][8]
static void AC_DelRequirement_f(void)
static cvar_t * ac_client_disconnect_action
static byte ac_send_buffer[AC_SEND_SIZE]
static void AC_SendHello(void)
static client_t * AC_ParseClient(void)
addrmatch_t * SV_MatchAddress(list_t *list, netadr_t *addr)
neterr_t NET_RunStream(netstream_t *s)
static void AC_ParseClientAck(void)
static const ac_cvarop_t ac_cvarops[]
CONST PIXELFORMATDESCRIPTOR int
void AC_ClientDisconnect(client_t *cl)
size_t FIFO_Write(fifo_t *fifo, const void *buffer, size_t len)
static void AC_ParseCvar(char *data, int linenum, const char *path)
static cvar_t * ac_show_violation_reason
static void AC_SendPrefs(void)
static const cmdreg_t c_ac[]
void SV_AddMatch_f(list_t *list)
static void AC_Spin(void)
void SZ_Clear(sizebuf_t *buf)
struct ac_file_s ac_file_t
static void ac_disable_play_changed(cvar_t *self)
static void AC_SendChecks(void)
static void AC_ParseToken(char *data, int linenum, const char *path)