- change MSG_ReadString to return const char * and return a pointer

directly into the packet data.
- change a bunch of char *'s to const char *'s for the above.  Only
  thing that had trouble was the cl_nofake handler, which I changed to
  use a local buffer.
- add MSG_ReadStaticString which acts like the old MSG_ReadString,
  specifically that it uses a static buffer and tollerates
  unterminated strings.
- add a Q_strnlen function, and make strnlen use it if strnlen is
  undefined.
- Add a net_svc.h and net_svc.c which will preparse svc messages into
  structs, for easier handling.  Currently only soundlist and
  modellist are done.
This commit is contained in:
Adam Olsen 2001-10-18 04:44:58 +00:00
parent 1b1955551a
commit 18036b63d9
15 changed files with 249 additions and 53 deletions

View File

@ -53,7 +53,8 @@ int MSG_ReadByte (msg_t *msg);
int MSG_ReadShort (msg_t *msg); int MSG_ReadShort (msg_t *msg);
int MSG_ReadLong (msg_t *msg); int MSG_ReadLong (msg_t *msg);
float MSG_ReadFloat (msg_t *msg); float MSG_ReadFloat (msg_t *msg);
char *MSG_ReadString (msg_t *msg); const char *MSG_ReadString (msg_t *msg);
char *MSG_ReadStaticString (msg_t *msg);
char *MSG_ReadStringLine (msg_t *msg); char *MSG_ReadStringLine (msg_t *msg);
float MSG_ReadCoord (msg_t *msg); float MSG_ReadCoord (msg_t *msg);

View File

@ -30,5 +30,6 @@
#define string_h #define string_h
const char * Q_strcasestr (const char *haystack, const char *needle); const char * Q_strcasestr (const char *haystack, const char *needle);
size_t Q_strnlen (const char *s, size_t maxlen);
#endif // string_h #endif // string_h

View File

@ -93,6 +93,10 @@ extern int vsnprintf(char *s, size_t maxlen, const char *format, va_list arg);
#if !defined(strcasestr) #if !defined(strcasestr)
# define strcasestr Q_strcasestr # define strcasestr Q_strcasestr
#endif #endif
// FIXME: same as above
#if !defined(strnlen)
# define strnlen Q_strnlen
#endif
#undef field_offset #undef field_offset
#define field_offset(type,field) ((int)&(((type *)0)->field)) #define field_offset(type,field) ((int)&(((type *)0)->field))

View File

@ -40,7 +40,9 @@ static const char rcsid[] =
#include "QF/msg.h" #include "QF/msg.h"
#include "QF/qendian.h" #include "QF/qendian.h"
#include "QF/sys.h" #include "QF/sys.h"
#include "QF/string.h"
#include "compat.h"
/* /*
MESSAGE IO FUNCTIONS MESSAGE IO FUNCTIONS
@ -261,8 +263,36 @@ MSG_ReadFloat (msg_t *msg)
return dat.f; return dat.f;
} }
char * const char *
MSG_ReadString (msg_t *msg) MSG_ReadString (msg_t *msg)
{
char *string;
int len, maxlen;
if (msg->readcount + 1 > msg->message->cursize) {
msg->badread = true;
return "";
}
string = &msg->message->data[msg->readcount];
maxlen = msg->message->cursize - msg->readcount;
len = strnlen (string, maxlen);
if (len == maxlen) {
msg->badread = true;
return "";
}
msg->readcount += len + 1;
return string;
}
// Netchan_OutOfBandPrint is broken such that it strips the
// terminating nul, which means connection packets (amoung others)
// aren't nul-terminated. So I provide the old string function for
// connectionless-packet parsers to use.
char *
MSG_ReadStaticString (msg_t *msg)
{ {
static char string[2048]; static char string[2048];
int l, c; int l, c;

View File

@ -45,7 +45,7 @@ static const char rcsid[] =
const char * const char *
Q_strcasestr (const char *haystack, const char *needle) Q_strcasestr (const char *haystack, const char *needle)
{ {
int len = strlen (needle); size_t len = strlen (needle);
while (*haystack) { while (*haystack) {
if (!strncasecmp (haystack, needle, len)) if (!strncasecmp (haystack, needle, len))
return haystack; return haystack;
@ -53,3 +53,16 @@ Q_strcasestr (const char *haystack, const char *needle)
} }
return 0; return 0;
} }
/*
Q_strnlen
strlen with a cutoff
*/
size_t
Q_strnlen (const char *s, size_t maxlen)
{
size_t i;
for (i = 0; s[i] && i < maxlen; i++);
return i;
}

View File

@ -222,7 +222,7 @@ CL_ParseServerInfo (void)
{ {
char model_precache[MAX_MODELS][MAX_QPATH]; char model_precache[MAX_MODELS][MAX_QPATH];
char sound_precache[MAX_SOUNDS][MAX_QPATH]; char sound_precache[MAX_SOUNDS][MAX_QPATH];
char *str; const char *str;
int nummodels, numsounds, i; int nummodels, numsounds, i;
Con_DPrintf ("Serverinfo packet received.\n"); Con_DPrintf ("Serverinfo packet received.\n");

View File

@ -969,7 +969,7 @@ _Datagram_CheckNewConnections (void)
} }
if (command == CCREQ_RULE_INFO) { if (command == CCREQ_RULE_INFO) {
char *prevCvarName; const char *prevCvarName;
cvar_t *var; cvar_t *var;
// find the search start location // find the search start location
@ -1277,7 +1277,7 @@ _Datagram_Connect (const char *host)
int reps; int reps;
double start_time; double start_time;
int control; int control;
char *reason; const char *reason;
// see if we can resolve the host name // see if we can resolve the host name
if (dfunc.GetAddrFromName (host, &sendaddr) == -1) if (dfunc.GetAddrFromName (host, &sendaddr) == -1)

View File

@ -448,7 +448,7 @@ qboolean
SV_ReadClientMessage (void) SV_ReadClientMessage (void)
{ {
int cmd, ret; int cmd, ret;
char *s; const char *s;
do { do {
nextmsg: nextmsg:

54
qw/include/net_svc.h Normal file
View File

@ -0,0 +1,54 @@
/*
net_svc.h
(description)
Copyright (C) 1996-1997 Id Software, Inc.
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 2
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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifndef NET_SVC_H
#define NET_SVC_H
#include "QF/mathlib.h"
#include "QF/msg.h"
#include "bothdefs.h"
typedef struct net_svc_soundlist_s
{
byte startsound;
const char *sounds[MAX_SOUNDS + 1]; // space left for terminating empty string
byte nextsound;
} net_svc_soundlist_t;
typedef struct net_svc_modellist_s
{
byte startmodel;
const char *models[MAX_MODELS + 1]; // space left for terminating empty string
byte nextmodel;
} net_svc_modellist_t;
void NET_SVC_Soundlist_Parse (net_svc_soundlist_t *soundlist, msg_t *message);
void NET_SVC_Modellist_Parse (net_svc_modellist_t *modellist, msg_t *message);
#endif // NET_SVC_H

View File

@ -112,7 +112,7 @@ client_LIB_DEPS= libqfnet.la libasm.la $(qf_client_LIBS)
client_sources= cl_cam.c cl_cmd.c cl_cvar.c cl_demo.c cl_ents.c cl_input.c \ client_sources= cl_cam.c cl_cmd.c cl_cvar.c cl_demo.c cl_ents.c cl_input.c \
cl_main.c cl_misc.c cl_ngraph.c cl_parse.c cl_pred.c \ cl_main.c cl_misc.c cl_ngraph.c cl_parse.c cl_pred.c \
cl_screen.c cl_skin.c cl_slist.c cl_tent.c cl_view.c \ cl_screen.c cl_skin.c cl_slist.c cl_tent.c cl_view.c \
console.c locs.c sbar.c skin.c teamplay.c console.c locs.c net_svc.c sbar.c skin.c teamplay.c
# Software-rendering clients # Software-rendering clients

View File

@ -883,12 +883,12 @@ CL_ConnectionlessPacket (void)
Con_Printf ("Command packet from remote host. Ignored.\n"); Con_Printf ("Command packet from remote host. Ignored.\n");
return; return;
} }
s = MSG_ReadString (net_message); s = MSG_ReadStaticString (net_message);
strncpy (cmdtext, s, sizeof (cmdtext) - 1); strncpy (cmdtext, s, sizeof (cmdtext) - 1);
cmdtext[sizeof (cmdtext) - 1] = 0; cmdtext[sizeof (cmdtext) - 1] = 0;
s = MSG_ReadString (net_message); s = MSG_ReadStaticString (net_message);
while (*s && isspace ((int) *s)) while (*s && isspace ((int) *s))
s++; s++;
@ -923,7 +923,7 @@ CL_ConnectionlessPacket (void)
} }
// print command from somewhere // print command from somewhere
if (c == A2C_PRINT) { if (c == A2C_PRINT) {
s = MSG_ReadString (net_message); s = MSG_ReadStaticString (net_message);
if (SL_CheckStatus(NET_AdrToString (net_from), s)) if (SL_CheckStatus(NET_AdrToString (net_from), s))
{ {
Con_Printf("status response\n"); Con_Printf("status response\n");
@ -952,7 +952,7 @@ CL_ConnectionlessPacket (void)
if (c == S2C_CHALLENGE) { if (c == S2C_CHALLENGE) {
Con_Printf ("challenge\n"); Con_Printf ("challenge\n");
s = MSG_ReadString (net_message); s = MSG_ReadStaticString (net_message);
cls.challenge = atoi (s); cls.challenge = atoi (s);
if (strstr (s, "QF")) if (strstr (s, "QF"))
CL_AddQFInfoKeys (); CL_AddQFInfoKeys ();
@ -964,7 +964,7 @@ CL_ConnectionlessPacket (void)
{ {
Con_Printf("Master Server Reply\n"); Con_Printf("Master Server Reply\n");
clcp_temp = MSG_ReadByte (net_message); clcp_temp = MSG_ReadByte (net_message);
s = MSG_ReadString (net_message); s = MSG_ReadStaticString (net_message);
MSL_ParseServerList(s); MSL_ParseServerList(s);
return; return;
} }

View File

@ -64,6 +64,7 @@ static const char rcsid[] =
#include "client.h" #include "client.h"
#include "compat.h" #include "compat.h"
#include "host.h" #include "host.h"
#include "net_svc.h"
#include "pmove.h" #include "pmove.h"
#include "protocol.h" #include "protocol.h"
#include "sbar.h" #include "sbar.h"
@ -427,7 +428,7 @@ CL_ParseDownload (void)
} }
if (size == -2) { if (size == -2) {
char *newname = MSG_ReadString (net_message); const char *newname = MSG_ReadString (net_message);
if (strncmp (newname, cls.downloadname, strlen (cls.downloadname)) if (strncmp (newname, cls.downloadname, strlen (cls.downloadname))
|| strstr (newname + strlen (cls.downloadname), "/")) { || strstr (newname + strlen (cls.downloadname), "/")) {
@ -612,7 +613,7 @@ void
CL_ParseServerData (void) CL_ParseServerData (void)
{ {
char fn[MAX_OSPATH]; char fn[MAX_OSPATH];
char *str; const char *str;
int protover; int protover;
qboolean cflag = false; qboolean cflag = false;
@ -724,16 +725,15 @@ CL_ClearBaselines (void)
void void
CL_ParseSoundlist (void) CL_ParseSoundlist (void)
{ {
char *str; const char *str;
int numsounds, n; int numsounds, i;
net_svc_soundlist_t soundlist;
// precache sounds // precache sounds
// memset (cl.sound_precache, 0, sizeof(cl.sound_precache)); NET_SVC_Soundlist_Parse (&soundlist, net_message);
numsounds = MSG_ReadByte (net_message); for (i = 0, numsounds = soundlist.startsound;; i++) {
str = soundlist.sounds[i];
for (;;) {
str = MSG_ReadString (net_message);
if (!str[0]) if (!str[0])
break; break;
numsounds++; numsounds++;
@ -742,12 +742,11 @@ CL_ParseSoundlist (void)
strcpy (cl.sound_name[numsounds], str); strcpy (cl.sound_name[numsounds], str);
} }
n = MSG_ReadByte (net_message); if (soundlist.nextsound) {
if (n) {
MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
MSG_WriteString (&cls.netchan.message, MSG_WriteString (&cls.netchan.message,
va (soundlist_name, cl.servercount, n)); va (soundlist_name, cl.servercount,
soundlist.nextsound));
return; return;
} }
@ -759,44 +758,45 @@ CL_ParseSoundlist (void)
void void
CL_ParseModellist (void) CL_ParseModellist (void)
{ {
int nummodels, n; int nummodels, i;
char *str; const char *str;
net_svc_modellist_t modellist;
// precache models and note certain default indexes // precache models and note certain default indexes
nummodels = MSG_ReadByte (net_message); NET_SVC_Modellist_Parse (&modellist, net_message);
for (;;) { for (i = 0, nummodels = modellist.startmodel;; i++) {
str = MSG_ReadString (net_message); str = modellist.models[i];
if (!str[0]) if (!str[0])
break; break;
nummodels++; nummodels++;
if (nummodels == MAX_MODELS) if (nummodels == MAX_MODELS)
Host_EndGame ("Server sent too many model_precache"); Host_EndGame ("Server sent too many model_precache");
strcpy (cl.model_name[nummodels], str); strncpy (cl.model_name[nummodels], str, MAX_QPATH - 1);
cl.model_name[nummodels][MAX_QPATH - 1] = '\0';
if (!strcmp (cl.model_name[nummodels], "progs/spike.mdl")) if (!strcmp (str, "progs/spike.mdl"))
cl_spikeindex = nummodels; cl_spikeindex = nummodels;
else if (!strcmp (cl.model_name[nummodels], "progs/player.mdl")) else if (!strcmp (str, "progs/player.mdl"))
cl_playerindex = nummodels; cl_playerindex = nummodels;
else if (!strcmp (cl.model_name[nummodels], "progs/flag.mdl")) else if (!strcmp (str, "progs/flag.mdl"))
cl_flagindex = nummodels; cl_flagindex = nummodels;
// for deadbodyfilter & gibfilter // for deadbodyfilter & gibfilter
else if (!strcmp (cl.model_name[nummodels], "progs/h_player.mdl")) else if (!strcmp (str, "progs/h_player.mdl"))
cl_h_playerindex = nummodels; cl_h_playerindex = nummodels;
else if (!strcmp (cl.model_name[nummodels], "progs/gib1.mdl")) else if (!strcmp (str, "progs/gib1.mdl"))
cl_gib1index = nummodels; cl_gib1index = nummodels;
else if (!strcmp (cl.model_name[nummodels], "progs/gib2.mdl")) else if (!strcmp (str, "progs/gib2.mdl"))
cl_gib2index = nummodels; cl_gib2index = nummodels;
else if (!strcmp (cl.model_name[nummodels], "progs/gib3.mdl")) else if (!strcmp (str, "progs/gib3.mdl"))
cl_gib3index = nummodels; cl_gib3index = nummodels;
} }
n = MSG_ReadByte (net_message); if (modellist.nextmodel) {
if (n) {
MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
MSG_WriteString (&cls.netchan.message, MSG_WriteString (&cls.netchan.message,
va (modellist_name, cl.servercount, n)); va (modellist_name, cl.servercount,
modellist.nextmodel));
return; return;
} }
@ -1099,7 +1099,7 @@ int received_framecount;
void void
CL_ParseServerMessage (void) CL_ParseServerMessage (void)
{ {
char *s; const char *s;
int cmd, i, j; int cmd, i, j;
received_framecount = host_framecount; received_framecount = host_framecount;
@ -1151,18 +1151,24 @@ CL_ParseServerMessage (void)
Host_EndGame ("Server disconnected"); Host_EndGame ("Server disconnected");
break; break;
case svc_print: case svc_print: {
char p[2048];
int j;
i = MSG_ReadByte (net_message); i = MSG_ReadByte (net_message);
s = MSG_ReadString (net_message); s = MSG_ReadString (net_message);
if (i == PRINT_CHAT) { if (i == PRINT_CHAT) {
// TODO: cl_nofake 2 -- accept fake messages from // TODO: cl_nofake 2 -- accept fake messages from
// teammates // teammates
char *p;
if (cl_nofake->int_val) { if (cl_nofake->int_val) {
for (p = s; *p; p++) do {
if (*p == 13) p[j] = (s[j] == 13) ? '#' : s[j];
*p = '#'; if (j == sizeof (p) - 1) {
p[j] = '\0';
break;
}
} while (s[j++]);
s = p;
} }
con_ormask = 128; con_ormask = 128;
S_LocalSound ("misc/talk.wav"); S_LocalSound ("misc/talk.wav");
@ -1170,7 +1176,7 @@ CL_ParseServerMessage (void)
Con_Printf ("%s", s); Con_Printf ("%s", s);
con_ormask = 0; con_ormask = 0;
break; break;
}
case svc_centerprint: case svc_centerprint:
SCR_CenterPrint (MSG_ReadString (net_message)); SCR_CenterPrint (MSG_ReadString (net_message));
break; break;

View File

@ -411,7 +411,7 @@ Analyze_Server_Packet (const byte * data, int len)
void void
Parse_Server_Packet () Parse_Server_Packet ()
{ {
char *s; const char *s;
int c, i, ii, iii, mask1, mask2; int c, i, ii, iii, mask1, mask2;
long seq1, seq2; long seq1, seq2;
@ -626,7 +626,7 @@ Parse_Server_Packet ()
Net_LogPrintf ("**QW OBSOLETE**"); Net_LogPrintf ("**QW OBSOLETE**");
break; break;
case svc_centerprint: case svc_centerprint:
Net_LogPrintf (MSG_ReadString (&packet)); Net_LogPrintf ("%s", MSG_ReadString (&packet));
break; break;
case svc_killedmonster: case svc_killedmonster:
break; break;

87
qw/source/net_svc.c Normal file
View File

@ -0,0 +1,87 @@
/*
net_svc.c
(description)
Copyright (C) 2001 Adam Olsen
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 2
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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
static const char rcsid[] =
"$Id$";
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifndef _WIN32
# ifdef HAVE_UNISTD_H
# include <unistd.h>
# endif
#else
# include <windows.h>
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include "QF/msg.h"
#include "compat.h"
#include "net_svc.h"
void
NET_SVC_Soundlist_Parse (net_svc_soundlist_t *soundlist, msg_t *message)
{
int i;
soundlist->startsound = MSG_ReadByte (message);
for (i = 0; i < MAX_MODELS; i++) {
soundlist->sounds[i] = MSG_ReadString (message);
if (!*soundlist->sounds[i])
break;
}
// this is a bit redundant, but I think the robustness is a good thing
soundlist->sounds[MAX_SOUNDS] = "";
soundlist->nextsound = MSG_ReadByte (message);
}
void
NET_SVC_Modellist_Parse (net_svc_modellist_t *modellist, msg_t *message)
{
int i;
modellist->startmodel = MSG_ReadByte (message);
for (i = 0; i < MAX_MODELS; i++) {
modellist->models[i] = MSG_ReadString (message);
if (!*modellist->models[i])
break;
}
// this is a bit redundant, but I think the robustness is a good thing
modellist->models[MAX_MODELS] = "";
modellist->nextmodel = MSG_ReadByte (message);
}

View File

@ -1673,7 +1673,7 @@ void
SV_ExecuteClientMessage (client_t *cl) SV_ExecuteClientMessage (client_t *cl)
{ {
int c; int c;
char *s; const char *s;
usercmd_t oldest, oldcmd, newcmd; usercmd_t oldest, oldcmd, newcmd;
client_frame_t *frame; client_frame_t *frame;
vec3_t o; vec3_t o;