Page 1 of 4

Replacing a quake3 function

Posted: Mon Jan 08, 2007 2:50 am
by nexus024
Does anyone know if its possible to replace

Code: Select all

   1.
      void trap_SendServerCommand( int clientNum, const char *text ) {
   2.
              syscall( G_SEND_SERVER_COMMAND, clientNum, text );
   3.
      } 
With this code

Code: Select all

   1.
      void trap_SendServerCommand( int clientNum, const char *text ) {
   2.
              // rain - hack - commands over 1022 chars will crash the
   3.
              // client upon receipt, so ignore them
   4.
              if( strlen( text ) > 1022 ) {
   5.
                      G_LogPrintf( "trap_SendServerCommand( %d, ... ) length exceeds 1022.\n", clientNum );
   6.
                      G_LogPrintf( "text [%s]\n", text );
   7.
                      return;
   8.
              }
   9.
              syscall( G_SEND_SERVER_COMMAND, clientNum, text );
  10.
      } 
This is a fix for the q3msgboom bug.

Posted: Mon Jan 08, 2007 8:25 am
by ^misantropia^
It'll only work when building a DLL, QVMs incorporate g_syscalls.asm instead. You could write a wrapper function that checks the length of the string, then calls trap_SendServerCommand(). Next up, replace all the calls to trap_SendServerCommand() in calls to your wrapper - except the call to it in your wrapper, of course.

Posted: Tue Jan 09, 2007 4:40 am
by nexus024
I am a bit unsure of what you are referring to as a wrapper. It sounds though that I would still have to recompile this new wrapper function with the source???

Posted: Tue Jan 09, 2007 9:55 am
by ^misantropia^
Correct, sir. A wrapper is merely a function that calls another function, massaging the input where it sees fit.

Posted: Tue Jan 09, 2007 6:44 pm
by nexus024
Ok, please let me know if I am on the right track here.

g_syscalls.c

Code: Select all

void trap_SendServerCommand( int clientNum, const char *text ) {

	syscall( G_SEND_SERVER_COMMAND, clientNum, text );

} 


void wrapper( int clientNum, const char *text ) {
	if( strlen( text ) < 1022 ) {
		trap_SendServerCommand( clientNum, text );
	}
	else if( strlen( text ) > 1022 ) {
		G_LogPrintf( "trap_SendServerCommand( %d, ... ) length exceeds 1022.\n", clientNum );
   		G_LogPrintf( "text [%s]\n", text );
   		return; 
	}
}
I found calls to trap_sendservercommand in g_bot.c, g_cmds.c, g_rankings.c, and g_target.c. I changed each one to point to my wrapper function instead of the sendservercommand function.

Another question... what q3 source must I use to compile this. I currently have the quake3 1.32b source code and the quake3 sdk for linux, but am unsure of which to use. All I am trying to do is patch my server so people can't use the q3msgboom and "kill" my server. I am assuming this is the correct approach?

Posted: Tue Jan 09, 2007 10:54 pm
by ^misantropia^
Ok, please let me know if I am on the right track here.
You are. I'd suggest renaming the wrapper function to something like trap_SendServerCommandWrapper() as it makes its purpose a bit more obvious.
I am assuming this is the correct approach?
It is.

Posted: Wed Jan 10, 2007 12:48 am
by nexus024
Any ideas?

Code: Select all

[root@localhost code]# make
WARNING: build system doesn't rely on GNU make. Spawning cons
  use ./unix/cons -h for help
./unix/cons
cpu : x86
OS  : Linux
libc: 2.3
configured for debug build
CFLAGS: -pipe -fsigned-char -g -Wall -Werror -O
gcc -pipe -fsigned-char -g -Wall -Werror -O -fPIC -Icgame -Igame -Iq3_ui -c debug-x86-Linux-2.3/Q3/game/game/ai_dmq3.c -o debug-x86-Linux-2.3/Q3/game/game/ai_dmq3.o
debug-x86-Linux-2.3/Q3/game/game/ai_dmq3.c:4433:8: extra tokens at end of #endif directive
cons: *** [debug-x86-Linux-2.3/Q3/game/game/ai_dmq3.o] Error 1
cons: errors constructing debug-x86-Linux-2.3/Q3/game/game/ai_dmq3.o
make: *** [default] Error 2

Posted: Wed Jan 10, 2007 12:58 am
by ^misantropia^
Yes. Take a look at game/ai_dmq3.c, line 4433. I wager there's something after the #endif directive that's not commented out.

Posted: Wed Jan 10, 2007 1:13 am
by nexus024

Code: Select all

debug-x86-Linux-2.3/Q3/game/game/g_bot.c: In function `Svcmd_AddBot_f':
debug-x86-Linux-2.3/Q3/game/game/g_bot.c:737: warning: implicit declaration of function `wrapper'
cons: *** [debug-x86-Linux-2.3/Q3/game/game/g_bot.o] Error 1
cons: errors constructing debug-x86-Linux-2.3/Q3/game/game/g_bot.o
make: *** [default] Error 2
g_bot.c

Code: Select all

// if this was issued during gameplay and we are playing locally,
	// go ahead and load the bot's media immediately
	if ( level.time - level.startTime > 1000 &&
		trap_Cvar_VariableIntegerValue( "cl_running" ) ) {
		wrapper( -1, "loaddefered\n" );	// FIXME: spelled wrong, but not changing for demo
	}

Posted: Wed Jan 10, 2007 1:15 am
by nexus024
Did I not setup my function correctly?

Posted: Wed Jan 10, 2007 1:29 am
by nexus024
I have been reading about this particular error message and it says to create a prototype for the function. I am unsure if that is the solution and if it is I don't know how to create a prototype for my function.

Posted: Wed Jan 10, 2007 2:35 am
by nexus024
Any suggestions?

Posted: Wed Jan 10, 2007 10:00 am
by torhu
A function prototype is just the function header without the body.

Just put this line in g_local.h, at the end is fine. Note the semicolon at the end:

Code: Select all

void trap_SendServerCommandWrapper( int clientNum, const char *text );
Whenever you call a function that's defined in another file, the compiler looks for a prototype like this so it can check that you're using the right number and types of arguments. But if I recall correctly, it's not mandatory. It's just considered a bad idea to leave it out. If there's no prototype, the compiler will assume that the arguments you give the function are what it expects, and that it returns an int.

Prototypes are also called declarations, like in the error message.

Posted: Wed Jan 10, 2007 11:41 am
by ^misantropia^
torhu wrote:But if I recall correctly, it's not mandatory.
It indeed isn't (but it is regarded as very bad practice). If you don't declare a prototype, the compiler will assume:

Code: Select all

int foo(...);
That is, a function returning int, taking any number of arguments.

Posted: Wed Jan 10, 2007 8:30 pm
by Silicone_Milk
wouldn't an example like the int foo(); function be a good thing at certain times?

Like say, for instance, that we wanted a function that added any numbers we give it together regardless of how many ints given as an argument.

In psuedo-code:

Code: Select all

    int foo(...) {
        if(argument # > 0){ 
            if(argument # = 1){
                argument0 + 0; //first argument  + nothing since we dont have another argument to add. 
                }
            else{
                 while(argument # != max_arguments){
                      the_argument = first argument + next argument;
                      the_argument = the_argument + next argument after last added argument; 
                      return the_argument; 
                   }
}
 
        
Although, I kinda think this would be a retarded way of going about doing things. Hypothetically, however, could this not be a useful thing to do?

Posted: Wed Jan 10, 2007 9:08 pm
by nexus024
Thank you all for your help... it finally compiled with no errors!!!

I notice that in /install/baseq3 there are three files: cgamei386.so, qagamei386.so , and uii386.so. Also there is a vm folder that contains cgame.qvm and ui.qvm files. In looking at my quake3 server the only file I use out of all of those is the qagamei386.so in my baseq3 folder. Does this mean I just replace my old file with this new patched one and the q3msgboom problem is solved? Or is there something I must do with these qvm files?

Posted: Wed Jan 10, 2007 10:00 pm
by ^misantropia^
Hmm, what point release are you running? QVMs (Q3 virtual machine files) have been the standard for a long, long time now.

Posted: Wed Jan 10, 2007 10:11 pm
by nexus024
Q3 Linux 1.32c

Posted: Thu Jan 11, 2007 12:11 am
by ^misantropia^
In that case you can safely delete the shared object (the .so). Place the *.qvm files in a directory 'vm', zip it up and save with the extension .pk3 and your mod is ready for distribution.

Posted: Thu Jan 11, 2007 12:43 am
by nexus024
Ok that might be a problem.... I just realized that the .so file is required for my q3as 1.99q mod that I run. What needs to be done so I can continue using q3as 1.99q mod?

Posted: Thu Jan 11, 2007 10:36 am
by ^misantropia^
You can't, really. Either you use your qagame.qvm or the q3as qagame.so but not both.

Posted: Thu Jan 11, 2007 3:25 pm
by nexus024
I know this can be done because I know of a server running the q3as mod and they have their server patched. Can you think of any way they accomplished this?

Posted: Thu Jan 11, 2007 9:50 pm
by ^misantropia^
Not possible unless you have access to the q3as source (or if you were willing to do a total rewrite of it).

Posted: Thu Jan 11, 2007 11:04 pm
by AnthonyJ
Its corrected engineside in ioq3 - rev 95 of trunk/code/server/sv_main.c, so that'll be how the other server is patched, I guess.

FWIW, the actual issue is that its exceeding sizeof( client->reliableCommands[index] ) as used in *_AddServerCommand() - which is MAX_STRING_CHARS (1024) bytes long.

Something downstream in the client end probably doesnt like the incomplete command.

Posted: Fri Jan 12, 2007 4:28 am
by nexus024
Since the fix is engine side, as you say, can i just replace sv_main.c with the rev 95 version, recompile the source again and use that somehow with the q3as mod? I'm also using point release 1.32c on my server.