- 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_ReadLong (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);
float MSG_ReadCoord (msg_t *msg);

View File

@ -30,5 +30,6 @@
#define string_h
const char * Q_strcasestr (const char *haystack, const char *needle);
size_t Q_strnlen (const char *s, size_t maxlen);
#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)
# define strcasestr Q_strcasestr
#endif
// FIXME: same as above
#if !defined(strnlen)
# define strnlen Q_strnlen
#endif
#undef field_offset
#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/qendian.h"
#include "QF/sys.h"
#include "QF/string.h"
#include "compat.h"
/*
MESSAGE IO FUNCTIONS
@ -261,8 +263,36 @@ MSG_ReadFloat (msg_t *msg)
return dat.f;
}
char *
const char *
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];
int l, c;

View File

@ -45,7 +45,7 @@ static const char rcsid[] =
const char *
Q_strcasestr (const char *haystack, const char *needle)
{
int len = strlen (needle);
size_t len = strlen (needle);
while (*haystack) {
if (!strncasecmp (haystack, needle, len))
return haystack;
@ -53,3 +53,16 @@ Q_strcasestr (const char *haystack, const char *needle)
}
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 sound_precache[MAX_SOUNDS][MAX_QPATH];
char *str;
const char *str;
int nummodels, numsounds, i;
Con_DPrintf ("Serverinfo packet received.\n");

View File

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

View File

@ -448,7 +448,7 @@ qboolean
SV_ReadClientMessage (void)
{
int cmd, ret;
char *s;
const char *s;
do {
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 \
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 \
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

View File

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

View File

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

View File

@ -411,7 +411,7 @@ Analyze_Server_Packet (const byte * data, int len)
void
Parse_Server_Packet ()
{
char *s;
const char *s;
int c, i, ii, iii, mask1, mask2;
long seq1, seq2;
@ -626,7 +626,7 @@ Parse_Server_Packet ()
Net_LogPrintf ("**QW OBSOLETE**");
break;
case svc_centerprint:
Net_LogPrintf (MSG_ReadString (&packet));
Net_LogPrintf ("%s", MSG_ReadString (&packet));
break;
case svc_killedmonster:
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)
{
int c;
char *s;
const char *s;
usercmd_t oldest, oldcmd, newcmd;
client_frame_t *frame;
vec3_t o;