Port various netxcmd changes from SRB2Classic

based on commits:

Lift NetXCmd limits
Fix segfault when sending excessively large netcmds
Simplify NetXCmd client distribution
try fixing some crash with bogus netxcmds
This commit is contained in:
NepDisk 2025-12-09 21:20:49 -05:00
parent 3d67382b0d
commit 3e075e3e4e

View file

@ -188,20 +188,23 @@ tic_t firstconnectattempttime = 0;
// Must be a power of two
#define TEXTCMD_HASH_SIZE 4
typedef struct textcmdplayer_s
{
INT32 playernum;
UINT8 cmd[MAXTEXTCMD];
struct textcmdplayer_s *next;
} textcmdplayer_t;
typedef struct textcmdtic_s
{
tic_t tic;
textcmdplayer_t *playercmds[TEXTCMD_HASH_SIZE];
UINT8 *playercmds[MAXPLAYERS];
struct textcmdtic_s *next;
} textcmdtic_t;
typedef struct textcmdbuf_s textcmdbuf_t;
struct textcmdbuf_s
{
textcmdbuf_t *next;
UINT8 cmd[MAXTEXTCMD];
};
static textcmdbuf_t *textcmdbuf[MAXSPLITSCREENPLAYERS];
static ticcmd_t playercmds[MAXPLAYERS];
ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS];
static textcmdtic_t *textcmds[TEXTCMD_HASH_SIZE] = {NULL};
@ -287,23 +290,57 @@ void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(UINT8 **p, INT32 playernum))
listnetxcmd[id] = cmd_f;
}
static void WriteNetXCmd(UINT8 *cmd, netxcmd_t id, const void *param, size_t nparam)
{
cmd[0]++;
cmd[cmd[0]] = (UINT8)id;
if (param && nparam)
{
memcpy(&cmd[cmd[0]+1], param, nparam);
cmd[0] = (UINT8)(cmd[0] + (UINT8)nparam);
}
}
void SendNetXCmdForPlayer(UINT8 playerid, netxcmd_t id, const void *param, size_t nparam)
{
if (localtextcmd[playerid][0]+2+nparam > MAXTEXTCMD)
{
// for future reference: if (cht_debug) != debug disabled.
CONS_Alert(CONS_ERROR, M_GetText("NetXCmd buffer full, cannot add netcmd %d! (size: %d, needed: %s)\n"), id, localtextcmd[playerid][0], sizeu1(nparam));
textcmdbuf_t *buf = textcmdbuf[playerid];
if (2+nparam > MAXTEXTCMD)
{
CONS_Alert(CONS_ERROR, M_GetText("packet too large to fit NetXCmd, cannot add netcmd %d! (size: %s, max: %d)\n"), id, sizeu1(2+nparam), MAXTEXTCMD);
return;
}
// for future reference: if (cv_debug) != debug disabled.
CONS_Alert(CONS_NOTICE, M_GetText("NetXCmd buffer full, delaying netcmd %d... (size: %d, needed: %s)\n"), id, localtextcmd[playerid][0], sizeu1(nparam));
if (buf == NULL)
{
textcmdbuf[playerid] = Z_Malloc(sizeof(textcmdbuf_t), PU_STATIC, NULL);
textcmdbuf[playerid]->cmd[0] = 0;
textcmdbuf[playerid]->next = NULL;
WriteNetXCmd(textcmdbuf[playerid]->cmd, id, param, nparam);
return;
}
while (buf->next != NULL)
buf = buf->next;
if (buf->cmd[0]+2+nparam > MAXTEXTCMD)
{
buf->next = Z_Malloc(sizeof(textcmdbuf_t), PU_STATIC, NULL);
buf->next->cmd[0] = 0;
buf->next->next = NULL;
WriteNetXCmd(buf->next->cmd, id, param, nparam);
}
else
{
WriteNetXCmd(buf->cmd, id, param, nparam);
}
return;
}
localtextcmd[playerid][0]++;
localtextcmd[playerid][localtextcmd[playerid][0]] = (UINT8)id;
if (param && nparam)
{
memcpy(&localtextcmd[playerid][localtextcmd[playerid][0] + 1], param, nparam);
localtextcmd[playerid][0] = (UINT8)(localtextcmd[playerid][0] + (UINT8)nparam);
}
WriteNetXCmd(localtextcmd[playerid], id, param, nparam);
}
UINT8 GetFreeXCmdSize(UINT8 playerid)
@ -326,22 +363,13 @@ static void D_FreeTextcmd(tic_t tic)
if (textcmdtic)
{
INT32 i;
// Remove this tic from the list.
*tctprev = textcmdtic->next;
// Free all players.
for (i = 0; i < TEXTCMD_HASH_SIZE; i++)
for (INT32 i = 0; i < MAXPLAYERS; i++)
{
textcmdplayer_t *textcmdplayer = textcmdtic->playercmds[i];
while (textcmdplayer)
{
textcmdplayer_t *tcpnext = textcmdplayer->next;
Z_Free(textcmdplayer);
textcmdplayer = tcpnext;
}
Z_Free(textcmdtic->playercmds[i]);
}
// Free this tic's own memory.
@ -358,10 +386,8 @@ static UINT8* D_GetExistingTextcmd(tic_t tic, INT32 playernum)
// Do we have an entry for the tic? If so, look for player.
if (textcmdtic)
{
textcmdplayer_t *textcmdplayer = textcmdtic->playercmds[playernum & (TEXTCMD_HASH_SIZE - 1)];
while (textcmdplayer && textcmdplayer->playernum != playernum) textcmdplayer = textcmdplayer->next;
if (textcmdplayer) return textcmdplayer->cmd;
UINT8 *cmd = textcmdtic->playercmds[playernum];
if (cmd) return cmd;
}
return NULL;
@ -372,7 +398,6 @@ static UINT8* D_GetTextcmd(tic_t tic, INT32 playernum)
{
textcmdtic_t *textcmdtic = textcmds[tic & (TEXTCMD_HASH_SIZE - 1)];
textcmdtic_t **tctprev = &textcmds[tic & (TEXTCMD_HASH_SIZE - 1)];
textcmdplayer_t *textcmdplayer, **tcpprev;
// Look for the tic.
while (textcmdtic && textcmdtic->tic != tic)
@ -388,24 +413,11 @@ static UINT8* D_GetTextcmd(tic_t tic, INT32 playernum)
textcmdtic->tic = tic;
}
tcpprev = &textcmdtic->playercmds[playernum & (TEXTCMD_HASH_SIZE - 1)];
textcmdplayer = *tcpprev;
// Look for the player.
while (textcmdplayer && textcmdplayer->playernum != playernum)
{
tcpprev = &textcmdplayer->next;
textcmdplayer = textcmdplayer->next;
}
// If we don't have an entry for the player, make it.
if (!textcmdplayer)
{
textcmdplayer = *tcpprev = Z_Calloc(sizeof (textcmdplayer_t), PU_STATIC, NULL);
textcmdplayer->playernum = playernum;
}
if (!textcmdtic->playercmds[playernum])
textcmdtic->playercmds[playernum] = Z_Calloc(MAXTEXTCMD, PU_STATIC, NULL);
return textcmdplayer->cmd;
return textcmdtic->playercmds[playernum];
}
static boolean ExtraDataTicker(void)
@ -5061,11 +5073,17 @@ static void PT_ServerTics(SINT8 node, INT32 netconsole)
numtxtpak = *txtpak++;
for (j = 0; j < numtxtpak; j++)
{
INT32 k = *txtpak++; // playernum
INT32 playernum = *txtpak++; // playernum
const size_t txtsize = txtpak[0]+1;
if (playernum < 0 || playernum >= MAXPLAYERS)
{
CONS_Alert(CONS_WARNING, "Got bogus NetXCmd packet targetting player %d\n", playernum);
return;
}
if (i >= gametic) // Don't copy old net commands
memcpy(D_GetTextcmd(i, k), txtpak, txtsize);
memcpy(D_GetTextcmd(i, playernum), txtpak, txtsize);
txtpak += txtsize;
}
}
@ -5774,7 +5792,17 @@ static void CL_SendClientCmd(void)
memcpy(netbuffer->u.textcmd, localtextcmd[i], localtextcmd[i][0]+1);
// All extra data have been sent
if (HSendPacket(servernode, true, 0, localtextcmd[i][0]+1)) // Send can fail...
{
localtextcmd[i][0] = 0;
if (textcmdbuf[i] != NULL)
{
textcmdbuf_t *buf = textcmdbuf[i];
memcpy(localtextcmd[i], textcmdbuf[i]->cmd, textcmdbuf[i]->cmd[0]+1);
textcmdbuf[i] = textcmdbuf[i]->next;
Z_Free(buf);
}
}
}
}
}