243 lines
5.1 KiB
C
243 lines
5.1 KiB
C
/*
|
|
cl_debug.c - server message debugging
|
|
Copyright (C) 2018 Uncle Mike
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
*/
|
|
|
|
#include "common.h"
|
|
#include "client.h"
|
|
#include "net_encode.h"
|
|
#include "particledef.h"
|
|
#include "cl_tent.h"
|
|
#include "shake.h"
|
|
#include "hltv.h"
|
|
#include "input.h"
|
|
|
|
#define MSG_COUNT 32 // last 32 messages parsed
|
|
#define MSG_MASK (MSG_COUNT - 1)
|
|
|
|
const char *svc_strings[svc_lastmsg+1] =
|
|
{
|
|
"svc_bad",
|
|
"svc_nop",
|
|
"svc_disconnect",
|
|
"svc_event",
|
|
"svc_changing",
|
|
"svc_setview",
|
|
"svc_sound",
|
|
"svc_time",
|
|
"svc_print",
|
|
"svc_stufftext",
|
|
"svc_setangle",
|
|
"svc_serverdata",
|
|
"svc_lightstyle",
|
|
"svc_updateuserinfo",
|
|
"svc_deltatable",
|
|
"svc_clientdata",
|
|
"svc_resource",
|
|
"svc_pings",
|
|
"svc_particle",
|
|
"svc_restoresound",
|
|
"svc_spawnstatic",
|
|
"svc_event_reliable",
|
|
"svc_spawnbaseline",
|
|
"svc_temp_entity",
|
|
"svc_setpause",
|
|
"svc_signonnum",
|
|
"svc_centerprint",
|
|
"svc_unused27",
|
|
"svc_unused28",
|
|
"svc_unused29",
|
|
"svc_intermission",
|
|
"svc_finale",
|
|
"svc_cdtrack",
|
|
"svc_restore",
|
|
"svc_cutscene",
|
|
"svc_weaponanim",
|
|
"svc_bspdecal",
|
|
"svc_roomtype",
|
|
"svc_addangle",
|
|
"svc_usermessage",
|
|
"svc_packetentities",
|
|
"svc_deltapacketentities",
|
|
"svc_choke",
|
|
"svc_resourcelist",
|
|
"svc_deltamovevars",
|
|
"svc_resourcerequest",
|
|
"svc_customization",
|
|
"svc_crosshairangle",
|
|
"svc_soundfade",
|
|
"svc_filetxferfailed",
|
|
"svc_hltv",
|
|
"svc_director",
|
|
"svc_voiceinit",
|
|
"svc_voicedata",
|
|
"svc_deltapacketbones",
|
|
"svc_unused55",
|
|
"svc_resourcelocation",
|
|
"svc_querycvarvalue",
|
|
"svc_querycvarvalue2",
|
|
"svc_exec",
|
|
};
|
|
|
|
typedef struct
|
|
{
|
|
int command;
|
|
int starting_offset;
|
|
int frame_number;
|
|
} oldcmd_t;
|
|
|
|
typedef struct
|
|
{
|
|
oldcmd_t oldcmd[MSG_COUNT];
|
|
int currentcmd;
|
|
qboolean parsing;
|
|
} msg_debug_t;
|
|
|
|
static msg_debug_t cls_message_debug;
|
|
|
|
const char *CL_MsgInfo( int cmd )
|
|
{
|
|
static string sz;
|
|
|
|
Q_strcpy( sz, "???" );
|
|
|
|
if( cmd >= 0 && cmd <= svc_lastmsg )
|
|
{
|
|
// get engine message name
|
|
Q_strncpy( sz, svc_strings[cmd], sizeof( sz ));
|
|
}
|
|
else if( cmd > svc_lastmsg && cmd <= ( svc_lastmsg + MAX_USER_MESSAGES ))
|
|
{
|
|
int i;
|
|
|
|
for( i = 0; i < MAX_USER_MESSAGES; i++ )
|
|
{
|
|
if( clgame.msg[i].number == cmd )
|
|
{
|
|
Q_strncpy( sz, clgame.msg[i].name, sizeof( sz ));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return sz;
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
CL_Parse_Debug
|
|
|
|
enable message debugging
|
|
=====================
|
|
*/
|
|
void CL_Parse_Debug( qboolean enable )
|
|
{
|
|
cls_message_debug.parsing = enable;
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
CL_Parse_RecordCommand
|
|
|
|
record new message params into debug buffer
|
|
=====================
|
|
*/
|
|
void CL_Parse_RecordCommand( int cmd, int startoffset )
|
|
{
|
|
int slot;
|
|
|
|
if( cmd == svc_nop ) return;
|
|
|
|
slot = ( cls_message_debug.currentcmd++ & MSG_MASK );
|
|
cls_message_debug.oldcmd[slot].command = cmd;
|
|
cls_message_debug.oldcmd[slot].starting_offset = startoffset;
|
|
cls_message_debug.oldcmd[slot].frame_number = host.framecount;
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
CL_ResetFrame
|
|
=====================
|
|
*/
|
|
void CL_ResetFrame( frame_t *frame )
|
|
{
|
|
memset( &frame->graphdata, 0, sizeof( netbandwidthgraph_t ));
|
|
frame->receivedtime = host.realtime;
|
|
frame->valid = true;
|
|
frame->choked = false;
|
|
frame->latency = 0.0;
|
|
frame->time = cl.mtime[0];
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
CL_WriteErrorMessage
|
|
|
|
write net_message into buffer.dat for debugging
|
|
=====================
|
|
*/
|
|
static void CL_WriteErrorMessage( int current_count, sizebuf_t *msg )
|
|
{
|
|
const char *buffer_file = "buffer.dat";
|
|
file_t *fp;
|
|
|
|
fp = FS_Open( buffer_file, "wb", false );
|
|
if( !fp ) return;
|
|
|
|
FS_Write( fp, &cls.starting_count, sizeof( int ));
|
|
FS_Write( fp, ¤t_count, sizeof( int ));
|
|
FS_Write( fp, MSG_GetData( msg ), MSG_GetMaxBytes( msg ));
|
|
FS_Close( fp );
|
|
|
|
Con_Printf( "Wrote erroneous message to %s\n", buffer_file );
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
CL_WriteMessageHistory
|
|
|
|
list last 32 messages for debugging net troubleshooting
|
|
=====================
|
|
*/
|
|
void CL_WriteMessageHistory( void )
|
|
{
|
|
oldcmd_t *old, *failcommand;
|
|
sizebuf_t *msg = &net_message;
|
|
int i, thecmd;
|
|
|
|
if( !cls.initialized || cls.state == ca_disconnected )
|
|
return;
|
|
|
|
if( !cls_message_debug.parsing )
|
|
return;
|
|
|
|
Con_Printf( "Last %i messages parsed.\n", MSG_COUNT );
|
|
|
|
// finish here
|
|
thecmd = cls_message_debug.currentcmd - 1;
|
|
thecmd -= ( MSG_COUNT - 1 ); // back up to here
|
|
|
|
for( i = 0; i < MSG_COUNT - 1; i++ )
|
|
{
|
|
thecmd &= MSG_MASK;
|
|
old = &cls_message_debug.oldcmd[thecmd];
|
|
Con_Printf( "%i %04i %s\n", old->frame_number, old->starting_offset, CL_MsgInfo( old->command ));
|
|
thecmd++;
|
|
}
|
|
|
|
failcommand = &cls_message_debug.oldcmd[thecmd];
|
|
Con_Printf( "BAD: %3i:%s\n", MSG_GetNumBytesRead( msg ) - 1, CL_MsgInfo( failcommand->command ));
|
|
if( host_developer.value >= DEV_EXTENDED )
|
|
CL_WriteErrorMessage( MSG_GetNumBytesRead( msg ) - 1, msg );
|
|
cls_message_debug.parsing = false;
|
|
}
|