2004-09-24 02:45:00 +00:00
//This file should be easily portable.
//The biggest strength of this plugin system is that ALL interactions are performed via
//named functions, this makes it *really* easy to port plugins from one engine to annother.
# include "quakedef.h"
2004-09-30 22:51:15 +00:00
# ifdef PLUGINS
2005-12-15 19:15:39 +00:00
//#define GNUTLS
# ifdef GNUTLS
# if defined(_WIN32) && !defined(MINGW)
//lets rip stuff out of the header and supply a seperate dll.
//gnutls is huge.
//also this helps get around the whole msvc/mingw thing.
struct DSTRUCT ;
typedef struct DSTRUCT * gnutls_certificate_credentials ;
typedef gnutls_certificate_credentials gnutls_certificate_client_credentials ;
typedef struct DSTRUCT * gnutls_anon_client_credentials ;
struct gnutls_session_int ;
typedef struct gnutls_session_int * gnutls_session ;
typedef void * gnutls_transport_ptr ;
2011-05-19 13:34:07 +00:00
typedef enum gnutls_kx_algorithm { GNUTLS_KX_RSA = 1 , GNUTLS_KX_DHE_DSS ,
2005-12-15 19:15:39 +00:00
GNUTLS_KX_DHE_RSA , GNUTLS_KX_ANON_DH , GNUTLS_KX_SRP ,
GNUTLS_KX_RSA_EXPORT , GNUTLS_KX_SRP_RSA , GNUTLS_KX_SRP_DSS
} gnutls_kx_algorithm ;
2011-05-19 13:34:07 +00:00
typedef enum gnutls_certificate_type { GNUTLS_CRT_X509 = 1 , GNUTLS_CRT_OPENPGP
2005-12-15 19:15:39 +00:00
} gnutls_certificate_type ;
typedef enum gnutls_connection_end { GNUTLS_SERVER = 1 , GNUTLS_CLIENT } gnutls_connection_end ;
typedef enum gnutls_credentials_type { GNUTLS_CRD_CERTIFICATE = 1 , GNUTLS_CRD_ANON , GNUTLS_CRD_SRP } gnutls_credentials_type ;
typedef enum gnutls_close_request { GNUTLS_SHUT_RDWR = 0 , GNUTLS_SHUT_WR = 1 } gnutls_close_request ;
# define GNUTLS_E_AGAIN -28
# define GNUTLS_E_INTERRUPTED -52
int ( VARGS * gnutls_bye ) ( gnutls_session session , gnutls_close_request how ) ;
void ( VARGS * gnutls_perror ) ( int error ) ;
int ( VARGS * gnutls_handshake ) ( gnutls_session session ) ;
void ( VARGS * gnutls_transport_set_ptr ) ( gnutls_session session , gnutls_transport_ptr ptr ) ;
int ( VARGS * gnutls_certificate_type_set_priority ) ( gnutls_session session , const int * ) ;
int ( VARGS * gnutls_credentials_set ) ( gnutls_session , gnutls_credentials_type type , void * cred ) ;
int ( VARGS * gnutls_kx_set_priority ) ( gnutls_session session , const int * ) ;
int ( VARGS * gnutls_init ) ( gnutls_session * session , gnutls_connection_end con_end ) ;
int ( VARGS * gnutls_set_default_priority ) ( gnutls_session session ) ;
int ( VARGS * gnutls_certificate_allocate_credentials ) ( gnutls_certificate_credentials * sc ) ;
int ( VARGS * gnutls_anon_allocate_client_credentials ) ( gnutls_anon_client_credentials * sc ) ;
int ( VARGS * gnutls_global_init ) ( void ) ;
int ( VARGS * gnutls_record_send ) ( gnutls_session session , const void * data , size_t sizeofdata ) ;
int ( VARGS * gnutls_record_recv ) ( gnutls_session session , void * data , size_t sizeofdata ) ;
qboolean Init_GNUTLS ( void )
{
HMODULE hmod ;
hmod = LoadLibrary ( " gnutls.dll " ) ;
if ( ! hmod )
return false ;
gnutls_bye = ( void * ) GetProcAddress ( hmod , " gnutls_bye " ) ;
gnutls_perror = ( void * ) GetProcAddress ( hmod , " gnutls_perror " ) ;
gnutls_handshake = ( void * ) GetProcAddress ( hmod , " gnutls_handshake " ) ;
gnutls_transport_set_ptr = ( void * ) GetProcAddress ( hmod , " gnutls_transport_set_ptr " ) ;
gnutls_certificate_type_set_priority = ( void * ) GetProcAddress ( hmod , " gnutls_certificate_type_set_priority " ) ;
gnutls_credentials_set = ( void * ) GetProcAddress ( hmod , " gnutls_credentials_set " ) ;
gnutls_kx_set_priority = ( void * ) GetProcAddress ( hmod , " gnutls_kx_set_priority " ) ;
gnutls_init = ( void * ) GetProcAddress ( hmod , " gnutls_init " ) ;
gnutls_set_default_priority = ( void * ) GetProcAddress ( hmod , " gnutls_set_default_priority " ) ;
gnutls_certificate_allocate_credentials = ( void * ) GetProcAddress ( hmod , " gnutls_certificate_allocate_credentials " ) ;
gnutls_anon_allocate_client_credentials = ( void * ) GetProcAddress ( hmod , " gnutls_anon_allocate_client_credentials " ) ;
gnutls_global_init = ( void * ) GetProcAddress ( hmod , " gnutls_global_init " ) ;
gnutls_record_send = ( void * ) GetProcAddress ( hmod , " gnutls_record_send " ) ;
gnutls_record_recv = ( void * ) GetProcAddress ( hmod , " gnutls_record_recv " ) ;
if ( ! gnutls_bye | | ! gnutls_perror | | ! gnutls_handshake | | ! gnutls_transport_set_ptr
| | ! gnutls_certificate_type_set_priority | | ! gnutls_credentials_set
| | ! gnutls_kx_set_priority | | ! gnutls_init | | ! gnutls_set_default_priority
| | ! gnutls_certificate_allocate_credentials | | ! gnutls_anon_allocate_client_credentials
| | ! gnutls_global_init | | ! gnutls_record_send | | ! gnutls_record_recv )
{
Con_Printf ( " gnutls.dll doesn't contain all required exports \n " ) ;
FreeLibrary ( hmod ) ;
return false ;
}
return true ;
}
# else
# include <gnutls/gnutls.h>
qboolean Init_GNUTLS ( void ) { return true ; }
# endif
# endif
2004-09-24 02:45:00 +00:00
2006-02-11 02:09:43 +00:00
cvar_t plug_sbar = SCVAR ( " plug_sbar " , " 1 " ) ;
cvar_t plug_loaddefault = SCVAR ( " plug_loaddefault " , " 1 " ) ;
2005-01-15 17:46:40 +00:00
2009-11-04 21:16:50 +00:00
# ifdef GLQUAKE
2004-10-10 06:32:29 +00:00
# include "glquake.h"
2005-08-01 14:17:27 +00:00
# endif
2004-10-10 06:32:29 +00:00
2005-12-15 19:45:04 +00:00
//custom plugin builtins.
2009-07-18 20:21:02 +00:00
typedef qintptr_t ( EXPORT_FN * Plug_Builtin_t ) ( void * offset , quintptr_t mask , const qintptr_t * arg ) ;
2005-12-21 03:07:33 +00:00
void Plug_RegisterBuiltin ( char * name , Plug_Builtin_t bi , int flags ) ;
2005-12-15 19:45:04 +00:00
# define PLUG_BIF_DLLONLY 1
# define PLUG_BIF_QVMONLY 2
2006-01-02 22:55:56 +00:00
# define PLUG_BIF_NEEDSRENDERER 4
2005-12-15 19:45:04 +00:00
2005-11-29 13:32:15 +00:00
# include "netinc.h"
2004-09-24 02:45:00 +00:00
typedef struct plugin_s {
char * name ;
vm_t * vm ;
2005-12-15 19:15:39 +00:00
2006-01-29 03:45:00 +00:00
int blockcloses ;
2009-04-06 00:34:32 +00:00
void * inputptr ;
unsigned int inputbytes ;
2004-09-24 02:45:00 +00:00
int tick ;
int executestring ;
2005-12-15 19:15:39 +00:00
# ifndef SERVERONLY
2005-01-13 16:50:37 +00:00
int conexecutecommand ;
2004-09-26 00:30:42 +00:00
int menufunction ;
2004-10-10 06:32:29 +00:00
int sbarlevel [ 3 ] ; //0 - main sbar, 1 - supplementry sbar sections (make sure these can be switched off), 2 - overlays (scoreboard). menus kill all.
int reschange ;
2004-09-24 02:45:00 +00:00
2005-08-03 23:14:59 +00:00
//protocol-in-a-plugin
int connectionlessclientpacket ;
2009-04-06 00:34:32 +00:00
//called to discolour console input text if they spelt it wrongly
int spellcheckmaskedtext ;
2005-12-15 19:15:39 +00:00
# endif
2006-01-01 09:01:15 +00:00
int svmsgfunction ;
int chatmsgfunction ;
int centerprintfunction ;
2005-11-30 05:01:43 +00:00
2004-09-24 02:45:00 +00:00
struct plugin_s * next ;
} plugin_t ;
2005-03-10 03:55:18 +00:00
void Plug_SubConsoleCommand ( console_t * con , char * line ) ;
2004-09-24 02:45:00 +00:00
plugin_t * currentplug ;
2005-12-15 19:15:39 +00:00
# ifndef SERVERONLY
# include "cl_plugin.inc"
# else
void Plug_Client_Init ( void ) { }
void Plug_Client_Close ( plugin_t * plug ) { }
# endif
2004-09-24 02:45:00 +00:00
void Plug_Init ( void ) ;
2005-08-03 23:14:59 +00:00
void Plug_Close ( plugin_t * plug ) ;
2004-09-24 02:45:00 +00:00
void Plug_Tick ( void ) ;
qboolean Plugin_ExecuteString ( void ) ;
void Plug_Shutdown ( void ) ;
static plugin_t * plugs ;
typedef struct {
char * name ;
Plug_Builtin_t func ;
2005-11-30 01:20:53 +00:00
int flags ;
2004-09-24 02:45:00 +00:00
} Plug_Plugins_t ;
Plug_Plugins_t * plugbuiltins ;
int numplugbuiltins ;
void Plug_RegisterBuiltin ( char * name , Plug_Builtin_t bi , int flags )
{
//randomize the order a little.
int newnum ;
2005-12-15 19:15:39 +00:00
2005-12-06 15:39:57 +00:00
newnum = ( rand ( ) % 128 ) + 1 ;
2004-09-24 02:45:00 +00:00
while ( newnum < numplugbuiltins & & plugbuiltins [ newnum ] . func )
newnum + = 128 ;
2004-12-04 16:26:22 +00:00
if ( newnum > = numplugbuiltins )
2004-09-24 02:45:00 +00:00
{
2008-05-09 14:22:37 +00:00
int newbuiltins = newnum + 128 ;
plugbuiltins = BZ_Realloc ( plugbuiltins , sizeof ( Plug_Plugins_t ) * newbuiltins ) ;
memset ( plugbuiltins + numplugbuiltins , 0 , sizeof ( Plug_Plugins_t ) * ( newbuiltins - numplugbuiltins ) ) ;
numplugbuiltins = newbuiltins ;
2004-09-24 02:45:00 +00:00
}
//got an empty number.
2005-12-15 19:15:39 +00:00
Con_DPrintf ( " %s: %i \n " , name , newnum ) ;
2004-09-24 02:45:00 +00:00
plugbuiltins [ newnum ] . name = name ;
plugbuiltins [ newnum ] . func = bi ;
2005-11-30 01:20:53 +00:00
plugbuiltins [ newnum ] . flags = flags ;
2004-09-24 02:45:00 +00:00
}
/*
static void Plug_RegisterBuiltinIndex ( char * name , Plug_Builtin_t bi , int flags , int index ) //I d
{
//randomize the order a little.
int newnum ;
2005-12-15 19:15:39 +00:00
2004-09-24 02:45:00 +00:00
newnum = rand ( ) % 128 ;
while ( newnum + 1 < numplugbuiltins & & plugbuiltins [ newnum + 1 ] . func )
newnum + = 128 ;
newnum + + ;
2004-12-04 16:26:22 +00:00
if ( newnum > = numplugbuiltins )
2004-09-24 02:45:00 +00:00
{
numplugbuiltins = newnum + 128 ;
plugbuiltins = BZ_Realloc ( plugbuiltins , sizeof ( Plug_Plugins_t ) * numplugbuiltins ) ;
}
//got an empty number.
plugbuiltins [ newnum ] . name = name ;
plugbuiltins [ newnum ] . func = bi ;
}
*/
2011-01-29 21:01:40 +00:00
static qintptr_t Plug_FindBuiltin ( qboolean native , char * p )
2004-09-24 02:45:00 +00:00
{
int i ;
for ( i = 0 ; i < numplugbuiltins ; i + + )
if ( plugbuiltins [ i ] . name )
2007-10-11 15:40:28 +00:00
if ( p & & ! strcmp ( plugbuiltins [ i ] . name , p ) )
2005-11-30 01:20:53 +00:00
{
2011-01-29 21:01:40 +00:00
if ( ! native & & plugbuiltins [ i ] . flags & PLUG_BIF_DLLONLY )
2005-11-30 01:20:53 +00:00
return 0 ; //block it, if not native
2011-01-29 21:01:40 +00:00
if ( native & & plugbuiltins [ i ] . flags & PLUG_BIF_QVMONLY )
2005-11-30 01:20:53 +00:00
return 0 ; //block it, if not native
2004-09-24 02:45:00 +00:00
return - i ;
2005-11-30 01:20:53 +00:00
}
2004-09-24 02:45:00 +00:00
return 0 ;
}
2011-01-29 21:01:40 +00:00
qintptr_t VARGS Plug_GetBuiltin ( void * offset , quintptr_t mask , const qintptr_t * args )
{
char * p = ( char * ) VM_POINTER ( args [ 0 ] ) ;
return Plug_FindBuiltin ( ! offset , p ) ;
}
2004-09-24 02:45:00 +00:00
2010-11-02 23:17:25 +00:00
int Plug_SystemCallsVM ( void * offset , quintptr_t mask , int fn , const int * arg )
2004-09-24 02:45:00 +00:00
{
2009-07-18 20:21:02 +00:00
# if FTE_WORDSIZE == 32
# define args arg
# else
qintptr_t args [ 9 ] ;
args [ 0 ] = arg [ 0 ] ;
args [ 1 ] = arg [ 1 ] ;
args [ 2 ] = arg [ 2 ] ;
args [ 3 ] = arg [ 3 ] ;
args [ 4 ] = arg [ 4 ] ;
args [ 5 ] = arg [ 5 ] ;
args [ 6 ] = arg [ 6 ] ;
args [ 7 ] = arg [ 7 ] ;
args [ 8 ] = arg [ 8 ] ;
# endif
2004-09-24 02:45:00 +00:00
fn = fn + 1 ;
if ( fn > = 0 & & fn < numplugbuiltins & & plugbuiltins [ fn ] . func ! = NULL )
2011-06-03 03:10:39 +00:00
return plugbuiltins [ fn ] . func ( offset , mask , ( qintptr_t * ) args ) ;
2009-07-18 20:21:02 +00:00
# undef args
2004-09-24 02:45:00 +00:00
Sys_Error ( " QVM Plugin tried calling invalid builtin %i " , fn ) ;
return 0 ;
}
//I'm not keen on this.
//but dlls call it without saying what sort of vm it comes from, so I've got to have them as specifics
2010-11-02 23:17:25 +00:00
static qintptr_t EXPORT_FN Plug_SystemCallsNative ( qintptr_t arg , . . . )
2004-09-24 02:45:00 +00:00
{
2009-07-18 20:21:02 +00:00
qintptr_t args [ 9 ] ;
2004-09-24 02:45:00 +00:00
va_list argptr ;
va_start ( argptr , arg ) ;
2009-07-18 20:21:02 +00:00
args [ 0 ] = va_arg ( argptr , qintptr_t ) ;
args [ 1 ] = va_arg ( argptr , qintptr_t ) ;
args [ 2 ] = va_arg ( argptr , qintptr_t ) ;
args [ 3 ] = va_arg ( argptr , qintptr_t ) ;
args [ 4 ] = va_arg ( argptr , qintptr_t ) ;
args [ 5 ] = va_arg ( argptr , qintptr_t ) ;
args [ 6 ] = va_arg ( argptr , qintptr_t ) ;
args [ 7 ] = va_arg ( argptr , qintptr_t ) ;
args [ 8 ] = va_arg ( argptr , qintptr_t ) ;
2004-09-24 02:45:00 +00:00
va_end ( argptr ) ;
arg = - arg ;
if ( arg > = 0 & & arg < numplugbuiltins & & plugbuiltins [ arg ] . func )
return plugbuiltins [ arg ] . func ( NULL , ~ 0 , args ) ;
2009-10-06 00:32:28 +00:00
Sys_Error ( " DLL Plugin tried calling invalid builtin %i " , ( int ) arg ) ;
2004-09-24 02:45:00 +00:00
return 0 ;
}
plugin_t * Plug_Load ( char * file )
{
plugin_t * newplug ;
for ( newplug = plugs ; newplug ; newplug = newplug - > next )
{
if ( ! stricmp ( newplug - > name , file ) )
2005-08-03 23:14:59 +00:00
return newplug ;
2004-09-24 02:45:00 +00:00
}
newplug = Z_Malloc ( sizeof ( plugin_t ) + strlen ( file ) + 1 ) ;
newplug - > name = ( char * ) ( newplug + 1 ) ;
strcpy ( newplug - > name , file ) ;
2005-12-15 19:15:39 +00:00
2010-11-02 23:17:25 +00:00
newplug - > vm = VM_Create ( NULL , file , Plug_SystemCallsNative , Plug_SystemCallsVM ) ;
2004-09-24 02:45:00 +00:00
currentplug = newplug ;
if ( newplug - > vm )
{
2005-08-03 23:14:59 +00:00
Con_Printf ( " Created plugin %s \n " , file ) ;
2004-09-24 02:45:00 +00:00
newplug - > next = plugs ;
plugs = newplug ;
2011-01-29 21:01:40 +00:00
if ( ! VM_Call ( newplug - > vm , 0 , Plug_FindBuiltin ( true , " Plug_GetEngineFunction " ) ) )
2005-08-03 23:14:59 +00:00
{
Plug_Close ( newplug ) ;
return NULL ;
}
2004-10-10 06:32:29 +00:00
2005-12-15 19:15:39 +00:00
# ifndef SERVERONLY
2004-10-10 06:32:29 +00:00
if ( newplug - > reschange )
VM_Call ( newplug - > vm , newplug - > reschange , vid . width , vid . height ) ;
2005-12-15 19:15:39 +00:00
# endif
2004-09-24 02:45:00 +00:00
}
else
{
Z_Free ( newplug ) ;
newplug = NULL ;
}
currentplug = NULL ;
return newplug ;
}
2009-04-01 22:03:56 +00:00
int Plug_Emumerated ( const char * name , int size , void * param )
2004-09-24 02:45:00 +00:00
{
char vmname [ MAX_QPATH ] ;
2009-04-01 22:03:56 +00:00
Q_strncpyz ( vmname , name , sizeof ( vmname ) ) ;
2004-09-24 02:45:00 +00:00
vmname [ strlen ( vmname ) - strlen ( param ) ] = ' \0 ' ;
2005-12-15 19:15:39 +00:00
if ( ! Plug_Load ( vmname ) )
Con_Printf ( " Couldn't load plugin %s \n " , vmname ) ;
2004-09-24 02:45:00 +00:00
return true ;
}
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_Con_Print ( void * offset , quintptr_t mask , const qintptr_t * arg )
2004-09-24 02:45:00 +00:00
{
2010-02-06 01:25:04 +00:00
// if (qrenderer == QR_NONE)
2007-03-28 13:27:35 +00:00
// return false;
2005-12-15 19:15:39 +00:00
Con_Printf ( " %s " , ( char * ) VM_POINTER ( arg [ 0 ] ) ) ;
2004-09-24 02:45:00 +00:00
return 0 ;
}
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_Sys_Error ( void * offset , quintptr_t mask , const qintptr_t * arg )
2004-09-24 02:45:00 +00:00
{
Sys_Error ( " %s " , ( char * ) offset + arg [ 0 ] ) ;
return 0 ;
}
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_Sys_Milliseconds ( void * offset , quintptr_t mask , const qintptr_t * arg )
2005-03-01 15:36:23 +00:00
{
return Sys_DoubleTime ( ) * 1000 ;
}
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_ExportToEngine ( void * offset , quintptr_t mask , const qintptr_t * arg )
2004-09-24 02:45:00 +00:00
{
2004-09-26 00:30:42 +00:00
char * name = ( char * ) VM_POINTER ( arg [ 0 ] ) ;
2008-05-25 01:08:54 +00:00
unsigned int functionid = VM_LONG ( arg [ 1 ] ) ;
2004-09-24 02:45:00 +00:00
if ( ! strcmp ( name , " Tick " ) )
2008-05-25 01:08:54 +00:00
currentplug - > tick = functionid ;
2004-09-24 02:45:00 +00:00
else if ( ! strcmp ( name , " ExecuteCommand " ) )
2008-05-25 01:08:54 +00:00
currentplug - > executestring = functionid ;
2005-12-15 19:15:39 +00:00
# ifndef SERVERONLY
2005-01-13 16:50:37 +00:00
else if ( ! strcmp ( name , " ConExecuteCommand " ) )
2008-05-25 01:08:54 +00:00
currentplug - > conexecutecommand = functionid ;
2004-09-26 00:30:42 +00:00
else if ( ! strcmp ( name , " MenuEvent " ) )
2008-05-25 01:08:54 +00:00
currentplug - > menufunction = functionid ;
2004-10-10 06:32:29 +00:00
else if ( ! strcmp ( name , " UpdateVideo " ) )
2008-05-25 01:08:54 +00:00
currentplug - > reschange = functionid ;
2004-10-13 07:24:59 +00:00
else if ( ! strcmp ( name , " SbarBase " ) ) //basic SBAR.
2008-05-25 01:08:54 +00:00
currentplug - > sbarlevel [ 0 ] = functionid ;
2004-10-13 07:24:59 +00:00
else if ( ! strcmp ( name , " SbarSupplement " ) ) //supplementry stuff - teamplay
2008-05-25 01:08:54 +00:00
currentplug - > sbarlevel [ 1 ] = functionid ;
2004-10-13 07:24:59 +00:00
else if ( ! strcmp ( name , " SbarOverlay " ) ) //overlay - scoreboard type stuff.
2008-05-25 01:08:54 +00:00
currentplug - > sbarlevel [ 2 ] = functionid ;
2005-08-03 23:14:59 +00:00
else if ( ! strcmp ( name , " ConnectionlessClientPacket " ) )
2008-05-25 01:08:54 +00:00
currentplug - > connectionlessclientpacket = functionid ;
2006-01-01 09:01:15 +00:00
else if ( ! strcmp ( name , " ServerMessageEvent " ) )
2008-05-25 01:08:54 +00:00
currentplug - > svmsgfunction = functionid ;
2006-01-01 09:01:15 +00:00
else if ( ! strcmp ( name , " ChatMessageEvent " ) )
2008-05-25 01:08:54 +00:00
currentplug - > chatmsgfunction = functionid ;
2006-01-01 09:01:15 +00:00
else if ( ! strcmp ( name , " CenterPrintMessage " ) )
2008-05-25 01:08:54 +00:00
currentplug - > centerprintfunction = functionid ;
2009-04-06 00:34:32 +00:00
else if ( ! strcmp ( name , " SpellCheckMaskedText " ) )
currentplug - > spellcheckmaskedtext = functionid ;
2005-12-15 19:15:39 +00:00
# endif
2004-09-24 02:45:00 +00:00
else
return 0 ;
return 1 ;
}
2004-10-10 06:32:29 +00:00
2005-12-15 19:15:39 +00:00
//retrieve a plugin's name
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_GetPluginName ( void * offset , quintptr_t mask , const qintptr_t * arg )
2005-12-15 19:15:39 +00:00
{
int plugnum = VM_LONG ( arg [ 0 ] ) ;
plugin_t * plug ;
//int plugnum (0 for current), char *buffer, int bufferlen
if ( VM_OOB ( arg [ 1 ] , arg [ 2 ] ) )
return false ;
if ( plugnum < = 0 )
{
Q_strncpyz ( VM_POINTER ( arg [ 1 ] ) , currentplug - > name , VM_LONG ( arg [ 2 ] ) ) ;
return true ;
}
for ( plug = plugs ; plug ; plug = plug - > next )
{
if ( - - plugnum = = 0 )
{
Q_strncpyz ( VM_POINTER ( arg [ 1 ] ) , plug - > name , VM_LONG ( arg [ 2 ] ) ) ;
return true ;
}
}
return false ;
}
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_ExportNative ( void * offset , quintptr_t mask , const qintptr_t * arg )
2005-11-30 01:20:53 +00:00
{
2012-04-24 07:59:11 +00:00
void * func ;
2005-11-30 01:20:53 +00:00
char * name = ( char * ) VM_POINTER ( arg [ 0 ] ) ;
arg + + ;
2012-04-24 07:59:11 +00:00
func = ( ( void * * ) arg ) [ 0 ] ;
2005-11-30 01:20:53 +00:00
2006-01-29 03:45:00 +00:00
if ( ! strcmp ( name , " UnsafeClose " ) )
{
//not used by the engine, but stops the user from being able to unload the plugin.
//this is useful for certain things, like if the plugin uses some external networking or direct disk access or whatever.
currentplug - > blockcloses + + ;
}
/*
else if ( ! strncmp ( name , " FS_LoadModule " ) ) //module as in pak/pk3
{
FS_RegisterModuleDriver ( name + 13 , func ) ;
currentplug - > blockcloses + + ;
}
*/
/*
else if ( ! strncmp ( name , " S_OutputDriver " ) ) //a sound driver (takes higher priority over the built-in ones)
{
S_RegisterOutputDriver ( name + 13 , func ) ;
currentplug - > blockcloses + + ;
}
*/
/*
else if ( ! strncmp ( name , " VID_DisplayDriver " ) ) //a video driver, loaded by name as given by vid_renderer
{
FS_RegisterModuleDriver ( , func ) ;
currentplug - > blockcloses + + ;
}
*/
2012-04-24 07:59:11 +00:00
# if defined(PLUGINS) && !defined(NOMEDIA) && !defined(SERVERONLY)
else if ( ! strcmp ( name , " Media_VideoDecoder " ) )
{
Media_RegisterDecoder ( currentplug , func ) ;
currentplug - > blockcloses + + ;
}
# endif
2006-01-29 03:45:00 +00:00
2005-12-15 19:15:39 +00:00
# ifndef SERVERONLY
2006-01-29 03:45:00 +00:00
else if ( ! strcmp ( name , " S_LoadSound " ) ) //a hook for loading extra types of sound (wav, mp3, ogg, midi, whatever you choose to support)
{
2006-02-11 14:51:36 +00:00
S_RegisterSoundInputPlugin ( ( void * ) func ) ;
2006-01-29 03:45:00 +00:00
currentplug - > blockcloses + + ;
}
2005-12-15 19:15:39 +00:00
# endif
2006-01-29 03:45:00 +00:00
else
2005-11-30 01:20:53 +00:00
return 0 ;
return 1 ;
}
2004-10-10 06:32:29 +00:00
typedef struct {
//Make SURE that the engine has resolved all cvar pointers into globals before this happens.
plugin_t * plugin ;
cvar_t * var ;
} plugincvararray_t ;
int plugincvararraylen ;
plugincvararray_t * plugincvararray ;
//qhandle_t Cvar_Register (char *name, char *defaultval, int flags, char *grouphint);
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_Cvar_Register ( void * offset , quintptr_t mask , const qintptr_t * arg )
2004-10-10 06:32:29 +00:00
{
char * name = VM_POINTER ( arg [ 0 ] ) ;
char * defaultvalue = VM_POINTER ( arg [ 1 ] ) ;
unsigned int flags = VM_LONG ( arg [ 2 ] ) ;
char * groupname = VM_POINTER ( arg [ 3 ] ) ;
cvar_t * var ;
int i ;
var = Cvar_Get ( name , defaultvalue , flags & 1 , groupname ) ;
for ( i = 0 ; i < plugincvararraylen ; i + + )
{
if ( ! plugincvararray [ i ] . var )
{ //hmm... a gap...
plugincvararray [ i ] . plugin = currentplug ;
plugincvararray [ i ] . var = var ;
return i ;
}
}
2007-09-17 20:35:39 +00:00
i = plugincvararraylen ;
2004-10-10 06:32:29 +00:00
plugincvararraylen + + ;
2007-09-17 20:35:39 +00:00
plugincvararray = BZ_Realloc ( plugincvararray , ( plugincvararraylen ) * sizeof ( plugincvararray_t ) ) ;
plugincvararray [ i ] . plugin = currentplug ;
plugincvararray [ i ] . var = var ;
return i ;
2004-10-10 06:32:29 +00:00
}
//int Cvar_Update, (qhandle_t handle, int modificationcount, char *stringv, float *floatv)); //stringv is 256 chars long, don't expect this function to do anything if modification count is unchanged.
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_Cvar_Update ( void * offset , quintptr_t mask , const qintptr_t * arg )
2004-10-10 06:32:29 +00:00
{
int handle ;
int modcount ;
char * stringv ; //255 bytes long.
float * floatv ;
cvar_t * var ;
handle = VM_LONG ( arg [ 0 ] ) ;
if ( handle < 0 | | handle > = plugincvararraylen )
return 0 ;
if ( plugincvararray [ handle ] . plugin ! = currentplug )
return 0 ; //I'm not letting you know what annother plugin has registered.
if ( VM_OOB ( arg [ 2 ] , 256 ) | | VM_OOB ( arg [ 3 ] , 4 ) ) //Oi, plugin - you screwed up
return 0 ;
modcount = VM_LONG ( arg [ 1 ] ) ;
stringv = VM_POINTER ( arg [ 2 ] ) ;
floatv = VM_POINTER ( arg [ 3 ] ) ;
var = plugincvararray [ handle ] . var ;
strcpy ( stringv , var - > string ) ;
* floatv = var - > value ;
return var - > modified ;
}
//void Cmd_Args(char *buffer, int buffersize)
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_Cmd_Args ( void * offset , quintptr_t mask , const qintptr_t * arg )
2004-09-24 02:45:00 +00:00
{
2004-09-26 00:30:42 +00:00
char * buffer = ( char * ) VM_POINTER ( arg [ 0 ] ) ;
2004-09-24 02:45:00 +00:00
char * args ;
args = Cmd_Args ( ) ;
if ( strlen ( args ) + 1 > arg [ 1 ] )
return 0 ;
strcpy ( buffer , args ) ;
return 1 ;
}
2004-10-10 06:32:29 +00:00
//void Cmd_Argv(int num, char *buffer, int buffersize)
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_Cmd_Argv ( void * offset , quintptr_t mask , const qintptr_t * arg )
2004-09-24 02:45:00 +00:00
{
2004-09-26 00:30:42 +00:00
char * buffer = ( char * ) VM_POINTER ( arg [ 1 ] ) ;
2004-09-24 02:45:00 +00:00
char * args ;
args = Cmd_Argv ( arg [ 0 ] ) ;
if ( strlen ( args ) + 1 > arg [ 2 ] )
return 0 ;
strcpy ( buffer , args ) ;
return 1 ;
}
2004-10-10 06:32:29 +00:00
//int Cmd_Argc(void)
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_Cmd_Argc ( void * offset , quintptr_t mask , const qintptr_t * arg )
2004-09-24 02:45:00 +00:00
{
return Cmd_Argc ( ) ;
}
2004-09-26 00:30:42 +00:00
2004-10-10 06:32:29 +00:00
//void Cvar_SetString (char *name, char *value);
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_Cvar_SetString ( void * offset , quintptr_t mask , const qintptr_t * arg )
2004-10-10 06:32:29 +00:00
{
char * name = VM_POINTER ( arg [ 0 ] ) ,
* value = VM_POINTER ( arg [ 1 ] ) ;
cvar_t * var = Cvar_Get ( name , value , 0 , " Plugin vars " ) ;
if ( var )
{
Cvar_Set ( var , value ) ;
return 1 ;
}
return 0 ;
}
//void Cvar_SetFloat (char *name, float value);
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_Cvar_SetFloat ( void * offset , quintptr_t mask , const qintptr_t * arg )
2004-10-10 06:32:29 +00:00
{
char * name = VM_POINTER ( arg [ 0 ] ) ;
float value = VM_FLOAT ( arg [ 1 ] ) ;
cvar_t * var = Cvar_Get ( name , " " , 0 , " Plugin vars " ) ; //"" because I'm lazy
if ( var )
{
Cvar_SetValue ( var , value ) ;
return 1 ;
}
return 0 ;
}
//void Cvar_GetFloat (char *name);
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_Cvar_GetFloat ( void * offset , quintptr_t mask , const qintptr_t * arg )
2004-10-10 06:32:29 +00:00
{
char * name = VM_POINTER ( arg [ 0 ] ) ;
int ret ;
cvar_t * var = Cvar_Get ( name , " " , 0 , " Plugin vars " ) ;
if ( var )
{
VM_FLOAT ( ret ) = var - > value ;
}
else
VM_FLOAT ( ret ) = 0 ;
return ret ;
}
//qboolean Cvar_GetString (char *name, char *retstring, int sizeofretstring);
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_Cvar_GetString ( void * offset , quintptr_t mask , const qintptr_t * arg )
2004-10-10 06:32:29 +00:00
{
char * name , * ret ;
int retsize ;
cvar_t * var ;
if ( VM_OOB ( arg [ 1 ] , arg [ 2 ] ) )
{
return false ;
}
name = VM_POINTER ( arg [ 0 ] ) ;
ret = VM_POINTER ( arg [ 1 ] ) ;
retsize = VM_LONG ( arg [ 2 ] ) ;
var = Cvar_Get ( name , " " , 0 , " Plugin vars " ) ;
if ( strlen ( var - > name ) + 1 > retsize )
return false ;
strcpy ( ret , var - > string ) ;
return true ;
}
//void Cmd_AddText (char *text, qboolean insert); //abort the entire engine.
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_Cmd_AddText ( void * offset , quintptr_t mask , const qintptr_t * arg )
2004-10-10 06:32:29 +00:00
{
if ( VM_LONG ( arg [ 1 ] ) )
2006-02-06 01:06:17 +00:00
Cbuf_InsertText ( VM_POINTER ( arg [ 0 ] ) , RESTRICT_LOCAL , false ) ;
2004-10-10 06:32:29 +00:00
else
Cbuf_AddText ( VM_POINTER ( arg [ 0 ] ) , RESTRICT_LOCAL ) ;
return 1 ;
2004-09-26 00:30:42 +00:00
}
2005-01-15 17:46:40 +00:00
int plugincommandarraylen ;
typedef struct {
plugin_t * plugin ;
char command [ 64 ] ;
} plugincommand_t ;
plugincommand_t * plugincommandarray ;
void Plug_Command_f ( void )
{
int i ;
char * cmd = Cmd_Argv ( 0 ) ;
plugin_t * oldplug = currentplug ;
for ( i = 0 ; i < plugincommandarraylen ; i + + )
{
if ( ! plugincommandarray [ i ] . plugin )
continue ; //don't check commands who's owners died.
if ( stricmp ( plugincommandarray [ i ] . command , cmd ) ) //not the right command
continue ;
currentplug = plugincommandarray [ i ] . plugin ;
if ( currentplug - > executestring )
VM_Call ( currentplug - > vm , currentplug - > executestring , 0 ) ;
break ;
}
currentplug = oldplug ;
}
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_Cmd_AddCommand ( void * offset , quintptr_t mask , const qintptr_t * arg )
2005-01-15 17:46:40 +00:00
{
int i ;
char * name = VM_POINTER ( arg [ 0 ] ) ;
for ( i = 0 ; i < plugincommandarraylen ; i + + )
{
if ( ! plugincommandarray [ i ] . plugin )
break ;
if ( plugincommandarray [ i ] . plugin = = currentplug )
{
if ( ! strcmp ( name , plugincommandarray [ i ] . command ) )
break ;
}
}
if ( i = = plugincommandarraylen )
{
plugincommandarraylen + + ;
plugincommandarray = BZ_Realloc ( plugincommandarray , plugincommandarraylen * sizeof ( plugincommand_t ) ) ;
}
Q_strncpyz ( plugincommandarray [ i ] . command , name , sizeof ( plugincommandarray [ i ] . command ) ) ;
2012-05-09 15:30:53 +00:00
if ( ! Cmd_AddCommand ( plugincommandarray [ i ] . command , Plug_Command_f ) )
2005-01-15 17:46:40 +00:00
return false ;
plugincommandarray [ i ] . plugin = currentplug ; //worked
return true ;
}
2005-08-12 00:22:38 +00:00
void VARGS Plug_FreeConCommands ( plugin_t * plug )
2005-01-15 17:46:40 +00:00
{
int i ;
for ( i = 0 ; i < plugincommandarraylen ; i + + )
{
if ( plugincommandarray [ i ] . plugin = = plug )
{
plugincommandarray [ i ] . plugin = NULL ;
Cmd_RemoveCommand ( plugincommandarray [ i ] . command ) ;
}
}
}
2005-03-01 15:36:23 +00:00
typedef enum {
STREAM_NONE ,
STREAM_SOCKET ,
2005-12-15 19:15:39 +00:00
STREAM_TLS ,
2005-11-30 01:20:53 +00:00
STREAM_OSFILE ,
2005-03-01 15:36:23 +00:00
STREAM_FILE
} plugstream_e ;
typedef struct {
plugin_t * plugin ;
plugstream_e type ;
int socket ;
2005-11-30 01:20:53 +00:00
struct {
char filename [ MAX_QPATH ] ;
qbyte * buffer ;
int buflen ;
int curlen ;
int curpos ;
} file ;
2005-12-15 19:15:39 +00:00
# ifdef GNUTLS
gnutls_session session ;
# endif
2005-03-01 15:36:23 +00:00
} pluginstream_t ;
pluginstream_t * pluginstreamarray ;
int pluginstreamarraylen ;
int Plug_NewStreamHandle ( plugstream_e type )
{
int i ;
2012-04-24 07:59:11 +00:00
for ( i = 1 ; i < pluginstreamarraylen ; i + + )
2005-03-01 15:36:23 +00:00
{
if ( ! pluginstreamarray [ i ] . plugin )
break ;
}
2012-04-24 07:59:11 +00:00
if ( i > = pluginstreamarraylen )
2005-03-01 15:36:23 +00:00
{
2012-04-24 07:59:11 +00:00
pluginstreamarraylen = i + 16 ;
2005-03-01 15:36:23 +00:00
pluginstreamarray = BZ_Realloc ( pluginstreamarray , pluginstreamarraylen * sizeof ( pluginstream_t ) ) ;
}
memset ( & pluginstreamarray [ i ] , 0 , sizeof ( pluginstream_t ) ) ;
pluginstreamarray [ i ] . plugin = currentplug ;
pluginstreamarray [ i ] . type = type ;
pluginstreamarray [ i ] . socket = - 1 ;
2005-11-30 01:20:53 +00:00
pluginstreamarray [ i ] . file . buffer = NULL ;
* pluginstreamarray [ i ] . file . filename = ' \0 ' ;
2005-03-01 15:36:23 +00:00
return i ;
}
2012-04-09 19:12:12 +00:00
# ifndef NACL
2005-03-01 15:36:23 +00:00
//EBUILTIN(int, NET_TCPListen, (char *ip, int port, int maxcount));
//returns a new socket with listen enabled.
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_Net_TCPListen ( void * offset , quintptr_t mask , const qintptr_t * arg )
2005-03-01 15:36:23 +00:00
{
int handle ;
int sock ;
struct sockaddr_qstorage address ;
int _true = 1 ;
2012-04-24 07:59:11 +00:00
int alen ;
2005-12-15 19:15:39 +00:00
2005-03-01 15:36:23 +00:00
char * localip = VM_POINTER ( arg [ 0 ] ) ;
unsigned short localport = VM_LONG ( arg [ 1 ] ) ;
int maxcount = VM_LONG ( arg [ 2 ] ) ;
netadr_t a ;
if ( localip )
{
if ( ! NET_StringToAdr ( localip , & a ) )
return - 1 ;
NetadrToSockadr ( & a , & address ) ;
}
else
{
memset ( & address , 0 , sizeof ( address ) ) ;
( ( struct sockaddr_in * ) & address ) - > sin_family = AF_INET ;
}
if ( ( ( struct sockaddr_in * ) & address ) - > sin_family = = AF_INET & & ! ( ( struct sockaddr_in * ) & address ) - > sin_port )
( ( struct sockaddr_in * ) & address ) - > sin_port = htons ( localport ) ;
# ifdef IPPROTO_IPV6
2005-03-20 02:57:11 +00:00
else if ( ( ( struct sockaddr_in6 * ) & address ) - > sin6_family = = AF_INET6 & & ! ( ( struct sockaddr_in6 * ) & address ) - > sin6_port )
2005-03-01 15:36:23 +00:00
( ( struct sockaddr_in6 * ) & address ) - > sin6_port = htons ( localport ) ;
# endif
2012-04-24 07:59:11 +00:00
switch ( ( ( struct sockaddr * ) & address ) - > sa_family )
{
case AF_INET :
alen = sizeof ( struct sockaddr_in ) ;
break ;
2012-05-10 12:53:36 +00:00
# ifdef IPPROTO_IPV6
2012-04-24 07:59:11 +00:00
case AF_INET6 :
alen = sizeof ( struct sockaddr_in6 ) ;
break ;
2012-05-10 12:53:36 +00:00
# endif
2012-04-24 07:59:11 +00:00
default :
return - 2 ;
}
2005-03-01 15:36:23 +00:00
if ( ( sock = socket ( ( ( struct sockaddr * ) & address ) - > sa_family , SOCK_STREAM , 0 ) ) = = - 1 )
{
Con_Printf ( " Failed to create socket \n " ) ;
return - 2 ;
}
2011-05-19 13:34:07 +00:00
if ( ioctlsocket ( sock , FIONBIO , ( u_long * ) & _true ) = = - 1 )
2005-03-01 15:36:23 +00:00
{
closesocket ( sock ) ;
return - 2 ;
}
2012-04-24 07:59:11 +00:00
setsockopt ( sock , SOL_SOCKET , SO_REUSEADDR , ( const char * ) & _true , sizeof ( _true ) ) ;
2005-03-01 15:36:23 +00:00
2012-04-24 07:59:11 +00:00
if ( bind ( sock , ( void * ) & address , alen ) = = - 1 )
2005-03-01 15:36:23 +00:00
{
closesocket ( sock ) ;
return - 2 ;
}
2012-04-24 07:59:11 +00:00
if ( listen ( sock , maxcount ) = = - 1 )
2005-03-01 15:36:23 +00:00
{
closesocket ( sock ) ;
return - 2 ;
}
handle = Plug_NewStreamHandle ( STREAM_SOCKET ) ;
pluginstreamarray [ handle ] . socket = sock ;
return handle ;
}
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_Net_Accept ( void * offset , quintptr_t mask , const qintptr_t * arg )
2005-03-01 15:36:23 +00:00
{
int handle = VM_LONG ( arg [ 0 ] ) ;
struct sockaddr_in address ;
int addrlen ;
int sock ;
int _true = 1 ;
2008-06-08 14:37:57 +00:00
char adr [ MAX_ADR_SIZE ] ;
2005-03-01 15:36:23 +00:00
if ( handle < 0 | | handle > = pluginstreamarraylen | | pluginstreamarray [ handle ] . plugin ! = currentplug | | pluginstreamarray [ handle ] . type ! = STREAM_SOCKET )
return - 2 ;
sock = pluginstreamarray [ handle ] . socket ;
2012-04-24 07:59:11 +00:00
if ( sock < 0 )
return - 1 ;
2005-03-01 15:36:23 +00:00
addrlen = sizeof ( address ) ;
sock = accept ( sock , ( struct sockaddr * ) & address , & addrlen ) ;
if ( sock < 0 )
return - 1 ;
2011-05-19 13:34:07 +00:00
if ( ioctlsocket ( sock , FIONBIO , ( u_long * ) & _true ) = = - 1 ) //now make it non blocking.
2005-03-01 15:36:23 +00:00
{
closesocket ( sock ) ;
return - 1 ;
}
if ( arg [ 2 ] & & ! VM_OOB ( arg [ 1 ] , arg [ 2 ] ) )
{
netadr_t a ;
char * s ;
SockadrToNetadr ( ( struct sockaddr_qstorage * ) & address , & a ) ;
2008-06-08 14:37:57 +00:00
s = NET_AdrToString ( adr , sizeof ( adr ) , a ) ;
2005-03-01 15:36:23 +00:00
Q_strncpyz ( VM_POINTER ( arg [ 1 ] ) , s , addrlen ) ;
}
handle = Plug_NewStreamHandle ( STREAM_SOCKET ) ;
pluginstreamarray [ handle ] . socket = sock ;
return handle ;
}
//EBUILTIN(int, NET_TCPConnect, (char *ip, int port));
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_Net_TCPConnect ( void * offset , quintptr_t mask , const qintptr_t * arg )
2005-03-01 15:36:23 +00:00
{
char * localip = VM_POINTER ( arg [ 0 ] ) ;
unsigned short localport = VM_LONG ( arg [ 1 ] ) ;
int handle ;
struct sockaddr_qstorage to , from ;
int sock ;
int _true = 1 ;
netadr_t a ;
2005-06-18 23:54:34 +00:00
if ( ! NET_StringToAdr ( localip , & a ) )
return - 1 ;
2005-03-01 15:36:23 +00:00
NetadrToSockadr ( & a , & to ) ;
if ( ( ( struct sockaddr_in * ) & to ) - > sin_family = = AF_INET & & ! ( ( struct sockaddr_in * ) & to ) - > sin_port )
( ( struct sockaddr_in * ) & to ) - > sin_port = htons ( localport ) ;
# ifdef IPPROTO_IPV6
2005-03-20 03:23:46 +00:00
else if ( ( ( struct sockaddr_in6 * ) & to ) - > sin6_family = = AF_INET6 & & ! ( ( struct sockaddr_in6 * ) & to ) - > sin6_port )
2005-03-01 15:36:23 +00:00
( ( struct sockaddr_in6 * ) & to ) - > sin6_port = htons ( localport ) ;
# endif
if ( ( sock = socket ( PF_INET , SOCK_STREAM , IPPROTO_TCP ) ) = = - 1 )
{
return - 2 ;
}
memset ( & from , 0 , sizeof ( from ) ) ;
( ( struct sockaddr * ) & from ) - > sa_family = ( ( struct sockaddr * ) & to ) - > sa_family ;
if ( bind ( sock , ( struct sockaddr * ) & from , sizeof ( from ) ) = = - 1 )
{
return - 2 ;
}
//not yet blocking. So no frequent attempts please...
//non blocking prevents connect from returning worthwhile sensible value.
if ( connect ( sock , ( struct sockaddr * ) & to , sizeof ( to ) ) = = - 1 )
{
closesocket ( sock ) ;
return - 2 ;
}
2005-12-15 19:15:39 +00:00
2011-05-19 13:34:07 +00:00
if ( ioctlsocket ( sock , FIONBIO , ( u_long * ) & _true ) = = - 1 ) //now make it non blocking.
2005-03-01 15:36:23 +00:00
{
return - 1 ;
}
handle = Plug_NewStreamHandle ( STREAM_SOCKET ) ;
pluginstreamarray [ handle ] . socket = sock ;
return handle ;
}
2005-12-15 19:15:39 +00:00
# ifdef GNUTLS
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_Net_SetTLSClient ( void * offset , unsigned int mask , const qintptr_t * arg )
2005-12-15 19:15:39 +00:00
{
static gnutls_anon_client_credentials anoncred ;
static gnutls_certificate_credentials xcred ;
int ret ;
long _false = false ;
long _true = true ;
/* Need to enable anonymous KX specifically. */
const int kx_prio [ ] = { GNUTLS_KX_ANON_DH , 0 } ;
const int cert_type_priority [ 3 ] = { GNUTLS_CRT_X509 , GNUTLS_CRT_OPENPGP , 0 } ;
pluginstream_t * stream ;
int handle = VM_LONG ( arg [ 0 ] ) ;
2007-02-26 03:00:25 +00:00
qboolean anon = false ;
2005-12-15 19:15:39 +00:00
if ( handle < 0 | | handle > = pluginstreamarraylen | | pluginstreamarray [ handle ] . plugin ! = currentplug )
{
Con_Printf ( " Plug_Net_SetTLSClient: socket does not belong to you (or is invalid) \n " ) ;
return - 2 ;
}
stream = & pluginstreamarray [ handle ] ;
if ( stream - > type ! = STREAM_SOCKET )
{ //not a socket - invalid
Con_Printf ( " Plug_Net_SetTLSClient: Not a socket handle \n " ) ;
return - 2 ;
}
2007-02-23 00:21:33 +00:00
ioctlsocket ( stream - > socket , FIONBIO , & _false ) ;
2005-12-15 19:15:39 +00:00
{
static qboolean needinit = true ;
if ( needinit )
{
gnutls_global_init ( ) ;
gnutls_anon_allocate_client_credentials ( & anoncred ) ;
gnutls_certificate_allocate_credentials ( & xcred ) ;
// gnutls_certificate_set_x509_trust_file (xcred, "ca.pem", GNUTLS_X509_FMT_PEM);
needinit = false ;
}
}
stream - > type = STREAM_TLS ;
// Initialize TLS session
gnutls_init ( & stream - > session , GNUTLS_CLIENT ) ;
// Use default priorities
gnutls_set_default_priority ( stream - > session ) ;
if ( anon )
{
gnutls_kx_set_priority ( stream - > session , kx_prio ) ;
gnutls_credentials_set ( stream - > session , GNUTLS_CRD_ANON , anoncred ) ;
}
else
{
gnutls_certificate_type_set_priority ( stream - > session , cert_type_priority ) ;
gnutls_credentials_set ( stream - > session , GNUTLS_CRD_CERTIFICATE , xcred ) ;
}
// connect to the peer
gnutls_transport_set_ptr ( stream - > session , ( gnutls_transport_ptr ) stream - > socket ) ;
// Perform the TLS handshake
ret = GNUTLS_E_AGAIN ;
while ( ( ret = = GNUTLS_E_AGAIN ) | | ( ret = = GNUTLS_E_INTERRUPTED ) )
{
ret = gnutls_handshake ( stream - > session ) ;
}
if ( ret < 0 )
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " *** TLS handshake failed (%i) \n " , ret ) ;
2005-12-15 19:15:39 +00:00
gnutls_perror ( ret ) ;
stream - > type = STREAM_SOCKET ; //go back to regular socket
gnutls_bye ( pluginstreamarray [ handle ] . session , GNUTLS_SHUT_RDWR ) ;
return - 2 ;
}
ioctlsocket ( stream - > socket , FIONBIO , & _true ) ;
return 0 ;
}
# endif
2012-04-09 19:12:12 +00:00
# endif
2005-12-15 19:15:39 +00:00
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_FS_Open ( void * offset , quintptr_t mask , const qintptr_t * arg )
2005-11-30 01:20:53 +00:00
{
//modes:
//1: read
//2: write
//char *name, int *handle, int mode
//return value is length of the file.
int handle ;
int * ret ;
char * data ;
if ( VM_OOB ( arg [ 1 ] , sizeof ( int ) ) )
return - 2 ;
ret = VM_POINTER ( arg [ 1 ] ) ;
2005-12-15 19:15:39 +00:00
2005-11-30 01:20:53 +00:00
if ( arg [ 2 ] = = 1 )
{
2009-05-24 10:11:17 +00:00
FS_LoadFile ( VM_POINTER ( arg [ 0 ] ) , ( void * * ) & data ) ;
2005-11-30 01:20:53 +00:00
if ( ! data )
return - 1 ;
handle = Plug_NewStreamHandle ( STREAM_FILE ) ;
pluginstreamarray [ handle ] . file . buffer = data ;
pluginstreamarray [ handle ] . file . curpos = 0 ;
pluginstreamarray [ handle ] . file . curlen = com_filesize ;
pluginstreamarray [ handle ] . file . buflen = com_filesize ;
* ret = handle ;
2005-12-15 19:15:39 +00:00
return com_filesize ;
2005-11-30 01:20:53 +00:00
}
else if ( arg [ 2 ] = = 2 )
{
data = BZ_Malloc ( 8192 ) ;
if ( ! data )
return - 1 ;
handle = Plug_NewStreamHandle ( STREAM_FILE ) ;
Q_strncpyz ( pluginstreamarray [ handle ] . file . filename , VM_POINTER ( arg [ 0 ] ) , MAX_QPATH ) ;
pluginstreamarray [ handle ] . file . buffer = data ;
pluginstreamarray [ handle ] . file . curpos = 0 ;
pluginstreamarray [ handle ] . file . curlen = 0 ;
pluginstreamarray [ handle ] . file . buflen = 8192 ;
* ret = handle ;
2005-12-15 19:15:39 +00:00
return com_filesize ;
2005-11-30 01:20:53 +00:00
}
else
return - 2 ;
}
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_memset ( void * offset , quintptr_t mask , const qintptr_t * arg )
2005-12-01 01:21:08 +00:00
{
2007-10-11 15:40:28 +00:00
void * p = VM_POINTER ( arg [ 0 ] ) ;
2005-12-01 01:21:08 +00:00
if ( VM_OOB ( arg [ 0 ] , arg [ 2 ] ) )
return false ;
2007-10-11 15:40:28 +00:00
if ( p )
memset ( p , VM_LONG ( arg [ 1 ] ) , VM_LONG ( arg [ 2 ] ) ) ;
2005-12-01 01:21:08 +00:00
return arg [ 0 ] ;
}
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_memcpy ( void * offset , quintptr_t mask , const qintptr_t * arg )
2005-12-01 01:21:08 +00:00
{
2007-10-11 15:40:28 +00:00
void * p1 = VM_POINTER ( arg [ 0 ] ) ;
void * p2 = VM_POINTER ( arg [ 1 ] ) ;
2005-12-01 01:21:08 +00:00
if ( VM_OOB ( arg [ 0 ] , arg [ 2 ] ) )
return false ;
2007-10-11 15:40:28 +00:00
2005-12-01 01:21:08 +00:00
if ( VM_OOB ( arg [ 1 ] , arg [ 2 ] ) )
return false ;
2007-10-11 15:40:28 +00:00
if ( p1 & & p2 )
memcpy ( p1 , p2 , VM_LONG ( arg [ 2 ] ) ) ;
2005-12-01 01:21:08 +00:00
return arg [ 0 ] ;
}
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_memmove ( void * offset , quintptr_t mask , const qintptr_t * arg )
2005-12-01 01:21:08 +00:00
{
2007-10-11 15:40:28 +00:00
void * p1 = VM_POINTER ( arg [ 0 ] ) ;
void * p2 = VM_POINTER ( arg [ 1 ] ) ;
2005-12-01 01:21:08 +00:00
if ( VM_OOB ( arg [ 0 ] , arg [ 2 ] ) )
return false ;
2007-10-11 15:40:28 +00:00
2005-12-01 01:21:08 +00:00
if ( VM_OOB ( arg [ 1 ] , arg [ 2 ] ) )
return false ;
2007-10-11 15:40:28 +00:00
if ( p1 & & p2 )
memmove ( p1 , p2 , VM_LONG ( arg [ 2 ] ) ) ;
2005-12-01 01:21:08 +00:00
return arg [ 0 ] ;
}
2005-11-30 01:20:53 +00:00
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_sqrt ( void * offset , quintptr_t mask , const qintptr_t * arg )
2005-12-06 15:39:57 +00:00
{
int ret ;
VM_FLOAT ( ret ) = sqrt ( VM_FLOAT ( arg [ 0 ] ) ) ;
return ret ;
}
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_sin ( void * offset , quintptr_t mask , const qintptr_t * arg )
2005-12-10 00:21:45 +00:00
{
int ret ;
VM_FLOAT ( ret ) = sin ( VM_FLOAT ( arg [ 0 ] ) ) ;
return ret ;
}
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_cos ( void * offset , quintptr_t mask , const qintptr_t * arg )
2005-12-10 00:21:45 +00:00
{
int ret ;
VM_FLOAT ( ret ) = cos ( VM_FLOAT ( arg [ 0 ] ) ) ;
return ret ;
}
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_atan2 ( void * offset , quintptr_t mask , const qintptr_t * arg )
2005-12-10 00:21:45 +00:00
{
int ret ;
VM_FLOAT ( ret ) = atan2 ( VM_FLOAT ( arg [ 0 ] ) , VM_FLOAT ( arg [ 1 ] ) ) ;
return ret ;
}
2005-12-06 15:39:57 +00:00
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_Net_Recv ( void * offset , quintptr_t mask , const qintptr_t * arg )
2005-03-01 15:36:23 +00:00
{
int read ;
int handle = VM_LONG ( arg [ 0 ] ) ;
void * dest = VM_POINTER ( arg [ 1 ] ) ;
int destlen = VM_LONG ( arg [ 2 ] ) ;
if ( VM_OOB ( arg [ 1 ] , arg [ 2 ] ) )
return - 2 ;
if ( handle < 0 | | handle > = pluginstreamarraylen | | pluginstreamarray [ handle ] . plugin ! = currentplug )
return - 2 ;
switch ( pluginstreamarray [ handle ] . type )
{
2012-04-09 19:12:12 +00:00
# ifndef NACL
2005-03-01 15:36:23 +00:00
case STREAM_SOCKET :
read = recv ( pluginstreamarray [ handle ] . socket , dest , destlen , 0 ) ;
if ( read < 0 )
{
if ( qerrno = = EWOULDBLOCK )
return - 1 ;
else
return - 2 ;
}
else if ( read = = 0 )
return - 2 ; //closed by remote connection.
return read ;
2012-04-09 19:12:12 +00:00
# endif
2005-12-15 19:15:39 +00:00
# ifdef GNUTLS
case STREAM_TLS :
read = gnutls_record_recv ( pluginstreamarray [ handle ] . session , dest , destlen ) ;
if ( read < 0 )
{
if ( read = = GNUTLS_E_AGAIN | | read = = - 9 )
return - 1 ;
else
{
Con_Printf ( " TLS Read Error %i (bufsize %i) \n " , read , destlen ) ;
return - 2 ;
}
}
else if ( read = = 0 )
return - 2 ; //closed by remote connection.
return read ;
# endif
2005-11-30 01:20:53 +00:00
case STREAM_FILE :
if ( pluginstreamarray [ handle ] . file . curlen - pluginstreamarray [ handle ] . file . curpos < destlen )
{
destlen = pluginstreamarray [ handle ] . file . curlen - pluginstreamarray [ handle ] . file . curpos ;
if ( destlen < 0 )
return - 2 ;
}
memcpy ( dest , pluginstreamarray [ handle ] . file . buffer + pluginstreamarray [ handle ] . file . curpos , destlen ) ;
pluginstreamarray [ handle ] . file . curpos + = destlen ;
return destlen ;
2005-03-01 15:36:23 +00:00
default :
return - 2 ;
}
}
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_Net_Send ( void * offset , quintptr_t mask , const qintptr_t * arg )
2005-03-01 15:36:23 +00:00
{
int written ;
int handle = VM_LONG ( arg [ 0 ] ) ;
void * src = VM_POINTER ( arg [ 1 ] ) ;
int srclen = VM_LONG ( arg [ 2 ] ) ;
if ( handle < 0 | | handle > = pluginstreamarraylen | | pluginstreamarray [ handle ] . plugin ! = currentplug )
return - 2 ;
switch ( pluginstreamarray [ handle ] . type )
{
2012-04-09 19:12:12 +00:00
# ifndef NACL
2005-03-01 15:36:23 +00:00
case STREAM_SOCKET :
written = send ( pluginstreamarray [ handle ] . socket , src , srclen , 0 ) ;
if ( written < 0 )
{
if ( qerrno = = EWOULDBLOCK )
return - 1 ;
else
return - 2 ;
}
else if ( written = = 0 )
return - 2 ; //closed by remote connection.
return written ;
2012-04-09 19:12:12 +00:00
# endif
2005-12-15 19:15:39 +00:00
# ifdef GNUTLS
case STREAM_TLS :
written = gnutls_record_send ( pluginstreamarray [ handle ] . session , src , srclen ) ;
if ( written < 0 )
{
if ( written = = GNUTLS_E_AGAIN | | written = = GNUTLS_E_INTERRUPTED )
return - 1 ;
else
{
Con_Printf ( " TLS Send Error %i (%i bytes) \n " , written , srclen ) ;
return - 2 ;
}
}
else if ( written = = 0 )
return - 2 ; //closed by remote connection.
return written ;
# endif
2005-11-30 01:20:53 +00:00
case STREAM_FILE :
if ( pluginstreamarray [ handle ] . file . buflen < pluginstreamarray [ handle ] . file . curpos + srclen )
{
pluginstreamarray [ handle ] . file . buflen = pluginstreamarray [ handle ] . file . curpos + srclen + 8192 ;
2005-12-15 19:15:39 +00:00
pluginstreamarray [ handle ] . file . buffer =
2005-11-30 01:20:53 +00:00
BZ_Realloc ( pluginstreamarray [ handle ] . file . buffer , pluginstreamarray [ handle ] . file . buflen ) ;
}
memcpy ( pluginstreamarray [ handle ] . file . buffer + pluginstreamarray [ handle ] . file . curpos , src , srclen ) ;
pluginstreamarray [ handle ] . file . curpos + = srclen ;
if ( pluginstreamarray [ handle ] . file . curpos > pluginstreamarray [ handle ] . file . curlen )
pluginstreamarray [ handle ] . file . curlen = pluginstreamarray [ handle ] . file . curpos ;
return - 2 ;
2005-03-01 15:36:23 +00:00
default :
return - 2 ;
}
}
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_Net_SendTo ( void * offset , quintptr_t mask , const qintptr_t * arg )
2005-08-03 23:14:59 +00:00
{
int written ;
int handle = VM_LONG ( arg [ 0 ] ) ;
void * src = VM_POINTER ( arg [ 1 ] ) ;
int srclen = VM_LONG ( arg [ 2 ] ) ;
netadr_t * address = VM_POINTER ( arg [ 3 ] ) ;
struct sockaddr_qstorage sockaddr ;
if ( handle = = - 1 )
{
NET_SendPacket ( NS_CLIENT , srclen , src , * address ) ;
return srclen ;
}
NetadrToSockadr ( address , & sockaddr ) ;
if ( handle < 0 | | handle > = pluginstreamarraylen | | pluginstreamarray [ handle ] . plugin ! = currentplug )
return - 2 ;
switch ( pluginstreamarray [ handle ] . type )
{
2012-04-09 19:12:12 +00:00
# ifndef NACL
2005-08-03 23:14:59 +00:00
case STREAM_SOCKET :
written = sendto ( pluginstreamarray [ handle ] . socket , src , srclen , 0 , ( struct sockaddr * ) & sockaddr , sizeof ( sockaddr ) ) ;
if ( written < 0 )
{
if ( qerrno = = EWOULDBLOCK )
return - 1 ;
else
return - 2 ;
}
else if ( written = = 0 )
return - 2 ; //closed by remote connection.
return written ;
2012-04-09 19:12:12 +00:00
# endif
2005-08-03 23:14:59 +00:00
default :
return - 2 ;
}
}
2005-03-01 15:36:23 +00:00
2005-12-15 19:15:39 +00:00
void Plug_Net_Close_Internal ( int handle )
{
2005-11-30 01:20:53 +00:00
switch ( pluginstreamarray [ handle ] . type )
{
2007-08-07 19:16:32 +00:00
case STREAM_FILE :
if ( * pluginstreamarray [ handle ] . file . filename )
2009-05-24 10:11:17 +00:00
{
2007-08-07 19:16:32 +00:00
COM_WriteFile ( pluginstreamarray [ handle ] . file . filename , pluginstreamarray [ handle ] . file . buffer , pluginstreamarray [ handle ] . file . curlen ) ;
2009-05-24 10:11:17 +00:00
BZ_Free ( pluginstreamarray [ handle ] . file . buffer ) ;
}
else
FS_FreeFile ( pluginstreamarray [ handle ] . file . buffer ) ;
2007-08-07 19:16:32 +00:00
break ;
case STREAM_NONE :
break ;
case STREAM_OSFILE :
break ;
case STREAM_SOCKET :
2012-04-09 19:12:12 +00:00
# ifndef NACL
2007-08-07 19:16:32 +00:00
closesocket ( pluginstreamarray [ handle ] . socket ) ;
2012-04-09 19:12:12 +00:00
# endif
2007-08-07 19:16:32 +00:00
break ;
2005-12-15 19:15:39 +00:00
case STREAM_TLS :
2007-08-07 19:16:32 +00:00
# ifdef GNUTLS
2005-12-15 19:15:39 +00:00
gnutls_bye ( pluginstreamarray [ handle ] . session , GNUTLS_SHUT_RDWR ) ;
pluginstreamarray [ handle ] . type = STREAM_SOCKET ;
Plug_Net_Close_Internal ( handle ) ;
return ;
# endif
2005-11-30 01:20:53 +00:00
break ;
}
2005-03-01 15:36:23 +00:00
pluginstreamarray [ handle ] . plugin = NULL ;
2005-12-15 19:15:39 +00:00
}
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_Net_Close ( void * offset , quintptr_t mask , const qintptr_t * arg )
2005-12-15 19:15:39 +00:00
{
int handle = VM_LONG ( arg [ 0 ] ) ;
if ( handle < 0 | | handle > = pluginstreamarraylen | | pluginstreamarray [ handle ] . plugin ! = currentplug )
return - 2 ;
2005-03-01 15:36:23 +00:00
2005-12-15 19:15:39 +00:00
Plug_Net_Close_Internal ( handle ) ;
2005-03-01 15:36:23 +00:00
return 0 ;
}
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_ReadInputBuffer ( void * offset , quintptr_t mask , const qintptr_t * arg )
2009-04-06 00:34:32 +00:00
{
void * buffer = VM_POINTER ( arg [ 0 ] ) ;
int bufferlen = VM_LONG ( arg [ 1 ] ) ;
if ( bufferlen > currentplug - > inputbytes )
bufferlen = currentplug - > inputbytes ;
memcpy ( buffer , currentplug - > inputptr , currentplug - > inputbytes ) ;
return bufferlen ;
}
2009-07-18 20:21:02 +00:00
qintptr_t VARGS Plug_UpdateInputBuffer ( void * offset , quintptr_t mask , const qintptr_t * arg )
2009-04-06 00:34:32 +00:00
{
void * buffer = VM_POINTER ( arg [ 0 ] ) ;
int bufferlen = VM_LONG ( arg [ 1 ] ) ;
if ( bufferlen > currentplug - > inputbytes )
bufferlen = currentplug - > inputbytes ;
memcpy ( currentplug - > inputptr , buffer , currentplug - > inputbytes ) ;
return bufferlen ;
}
2005-01-15 17:46:40 +00:00
void Plug_CloseAll_f ( void ) ;
2005-03-01 15:36:23 +00:00
void Plug_List_f ( void ) ;
2005-01-15 20:50:45 +00:00
void Plug_Close_f ( void ) ;
2005-01-15 17:46:40 +00:00
void Plug_Load_f ( void )
{
2005-06-18 23:54:34 +00:00
char * plugin ;
plugin = Cmd_Argv ( 1 ) ;
if ( ! * plugin )
{
Con_Printf ( " Loads a plugin \n " ) ;
Con_Printf ( " plug_load [pluginpath] \n " ) ;
2005-08-03 23:14:59 +00:00
Con_Printf ( " example pluginpath: plugins/blah \n " ) ;
Con_Printf ( " will load blahx86.dll or blah.so \n " ) ;
2005-06-18 23:54:34 +00:00
return ;
}
if ( ! Plug_Load ( plugin ) )
{
if ( ! Plug_Load ( va ( " plugins/%s " , plugin ) ) )
Con_Printf ( " Couldn't load plugin %s \n " , Cmd_Argv ( 1 ) ) ;
}
2005-01-15 17:46:40 +00:00
}
2005-08-26 22:56:51 +00:00
/*
2009-07-18 20:21:02 +00:00
static qintptr_t Test_SysCalls_Ex ( void * offset , quintptr_t mask , int fn , qintptr_t * arg )
2005-08-26 22:56:51 +00:00
{
switch ( fn )
{
case 1 :
Con_Printf ( " %s " , VM_POINTER ( arg [ 0 ] ) ) ;
break ;
default :
Con_Printf ( " Can't handle %i \n " , fn ) ;
}
return 0 ;
}
static int EXPORT_FN Test_SysCalls ( int arg , . . . )
{
return 0 ;
}
void VM_Test_f ( void )
{
vm_t * vm ;
vm = VM_Create ( NULL , " vm/test " , Test_SysCalls , Test_SysCalls_Ex ) ;
if ( vm )
{
VM_Call ( vm , 0 , " " ) ;
VM_Destroy ( vm ) ;
}
} */
2005-01-15 17:46:40 +00:00
2004-09-24 02:45:00 +00:00
void Plug_Init ( void )
{
2005-08-26 22:56:51 +00:00
// Cmd_AddCommand("testvm", VM_Test_f);
2005-01-15 17:46:40 +00:00
Cvar_Register ( & plug_sbar , " plugins " ) ;
Cvar_Register ( & plug_loaddefault , " plugins " ) ;
Cmd_AddCommand ( " plug_closeall " , Plug_CloseAll_f ) ;
2005-01-15 20:50:45 +00:00
Cmd_AddCommand ( " plug_close " , Plug_Close_f ) ;
2005-01-15 17:46:40 +00:00
Cmd_AddCommand ( " plug_load " , Plug_Load_f ) ;
2005-03-01 15:36:23 +00:00
Cmd_AddCommand ( " plug_list " , Plug_List_f ) ;
2005-01-15 17:46:40 +00:00
2011-01-29 21:01:40 +00:00
Plug_RegisterBuiltin ( " Plug_GetEngineFunction " , Plug_GetBuiltin , 0 ) ; //plugin wishes to find a builtin number.
2004-10-10 06:32:29 +00:00
Plug_RegisterBuiltin ( " Plug_ExportToEngine " , Plug_ExportToEngine , 0 ) ; //plugin has a call back that we might be interested in.
2005-11-30 01:20:53 +00:00
Plug_RegisterBuiltin ( " Plug_ExportNative " , Plug_ExportNative , PLUG_BIF_DLLONLY ) ;
2004-10-10 06:32:29 +00:00
Plug_RegisterBuiltin ( " Con_Print " , Plug_Con_Print , 0 ) ; //printf is not possible - qvm floats are never doubles, vararg floats in a cdecl call are always converted to doubles.
Plug_RegisterBuiltin ( " Sys_Error " , Plug_Sys_Error , 0 ) ;
2005-03-01 15:36:23 +00:00
Plug_RegisterBuiltin ( " Sys_Milliseconds " , Plug_Sys_Milliseconds , 0 ) ;
2004-10-10 06:32:29 +00:00
Plug_RegisterBuiltin ( " Com_Error " , Plug_Sys_Error , 0 ) ; //make zquake programmers happy.
2005-01-15 17:46:40 +00:00
Plug_RegisterBuiltin ( " Cmd_AddCommand " , Plug_Cmd_AddCommand , 0 ) ;
2004-10-10 06:32:29 +00:00
Plug_RegisterBuiltin ( " Cmd_Args " , Plug_Cmd_Args , 0 ) ;
Plug_RegisterBuiltin ( " Cmd_Argc " , Plug_Cmd_Argc , 0 ) ;
Plug_RegisterBuiltin ( " Cmd_Argv " , Plug_Cmd_Argv , 0 ) ;
Plug_RegisterBuiltin ( " Cmd_AddText " , Plug_Cmd_AddText , 0 ) ;
2004-09-24 02:45:00 +00:00
2004-10-10 06:32:29 +00:00
Plug_RegisterBuiltin ( " Cvar_Register " , Plug_Cvar_Register , 0 ) ;
2005-08-01 12:35:16 +00:00
Plug_RegisterBuiltin ( " Cvar_Update " , Plug_Cvar_Update , 0 ) ;
2004-10-10 06:32:29 +00:00
Plug_RegisterBuiltin ( " Cvar_SetString " , Plug_Cvar_SetString , 0 ) ;
Plug_RegisterBuiltin ( " Cvar_SetFloat " , Plug_Cvar_SetFloat , 0 ) ;
Plug_RegisterBuiltin ( " Cvar_GetString " , Plug_Cvar_GetString , 0 ) ;
Plug_RegisterBuiltin ( " Cvar_GetFloat " , Plug_Cvar_GetFloat , 0 ) ;
2012-04-09 19:12:12 +00:00
# ifndef NACL
2005-03-01 15:36:23 +00:00
Plug_RegisterBuiltin ( " Net_TCPListen " , Plug_Net_TCPListen , 0 ) ;
Plug_RegisterBuiltin ( " Net_Accept " , Plug_Net_Accept , 0 ) ;
Plug_RegisterBuiltin ( " Net_TCPConnect " , Plug_Net_TCPConnect , 0 ) ;
2005-12-15 19:15:39 +00:00
# ifdef GNUTLS
if ( Init_GNUTLS ( ) )
Plug_RegisterBuiltin ( " Net_SetTLSClient " , Plug_Net_SetTLSClient , 0 ) ;
# endif
2005-03-01 15:36:23 +00:00
Plug_RegisterBuiltin ( " Net_Recv " , Plug_Net_Recv , 0 ) ;
Plug_RegisterBuiltin ( " Net_Send " , Plug_Net_Send , 0 ) ;
2005-08-03 23:14:59 +00:00
Plug_RegisterBuiltin ( " Net_SendTo " , Plug_Net_SendTo , 0 ) ;
2005-03-01 15:36:23 +00:00
Plug_RegisterBuiltin ( " Net_Close " , Plug_Net_Close , 0 ) ;
2012-04-09 19:12:12 +00:00
# endif
2005-03-01 15:36:23 +00:00
2005-11-30 01:20:53 +00:00
Plug_RegisterBuiltin ( " FS_Open " , Plug_FS_Open , 0 ) ;
Plug_RegisterBuiltin ( " FS_Read " , Plug_Net_Recv , 0 ) ;
Plug_RegisterBuiltin ( " FS_Write " , Plug_Net_Send , 0 ) ;
Plug_RegisterBuiltin ( " FS_Close " , Plug_Net_Close , 0 ) ;
2005-12-01 01:21:08 +00:00
Plug_RegisterBuiltin ( " memset " , Plug_memset , 0 ) ;
Plug_RegisterBuiltin ( " memcpy " , Plug_memcpy , 0 ) ;
Plug_RegisterBuiltin ( " memmove " , Plug_memmove , 0 ) ;
2005-12-06 15:39:57 +00:00
Plug_RegisterBuiltin ( " sqrt " , Plug_sqrt , 0 ) ;
2005-12-10 00:21:45 +00:00
Plug_RegisterBuiltin ( " sin " , Plug_sin , 0 ) ;
Plug_RegisterBuiltin ( " cos " , Plug_cos , 0 ) ;
Plug_RegisterBuiltin ( " atan2 " , Plug_atan2 , 0 ) ;
2005-12-01 01:21:08 +00:00
2009-04-06 00:34:32 +00:00
Plug_RegisterBuiltin ( " ReadInputBuffer " , Plug_ReadInputBuffer , 0 ) ;
Plug_RegisterBuiltin ( " UpdateInputBuffer " , Plug_UpdateInputBuffer , 0 ) ;
2005-12-01 01:21:08 +00:00
2005-12-15 19:15:39 +00:00
Plug_Client_Init ( ) ;
2005-03-01 15:36:23 +00:00
2005-08-03 23:14:59 +00:00
if ( plug_loaddefault . value )
{
2004-09-24 02:45:00 +00:00
# ifdef _WIN32
2005-08-03 23:14:59 +00:00
COM_EnumerateFiles ( " plugins/*x86.dll " , Plug_Emumerated , " x86.dll " ) ;
2004-09-24 02:45:00 +00:00
# elif defined(__linux__)
2005-08-03 23:14:59 +00:00
COM_EnumerateFiles ( " plugins/*x86.so " , Plug_Emumerated , " x86.so " ) ;
2004-09-24 02:45:00 +00:00
# endif
2005-08-03 23:14:59 +00:00
COM_EnumerateFiles ( " plugins/*.qvm " , Plug_Emumerated , " .qvm " ) ;
}
2004-09-24 02:45:00 +00:00
}
void Plug_Tick ( void )
{
2005-01-15 17:46:40 +00:00
plugin_t * oldplug = currentplug ;
for ( currentplug = plugs ; currentplug ; currentplug = currentplug - > next )
2004-09-24 02:45:00 +00:00
{
2005-01-15 17:46:40 +00:00
if ( currentplug - > tick )
2004-09-24 02:45:00 +00:00
{
2005-01-15 17:46:40 +00:00
VM_Call ( currentplug - > vm , currentplug - > tick , ( int ) ( realtime * 1000 ) ) ;
2004-09-24 02:45:00 +00:00
}
}
2005-01-15 17:46:40 +00:00
currentplug = oldplug ;
2004-09-24 02:45:00 +00:00
}
2005-12-15 19:15:39 +00:00
# ifndef SERVERONLY
2004-10-10 06:32:29 +00:00
void Plug_ResChanged ( void )
{
plugin_t * oldplug = currentplug ;
for ( currentplug = plugs ; currentplug ; currentplug = currentplug - > next )
{
if ( currentplug - > reschange )
VM_Call ( currentplug - > vm , currentplug - > reschange , vid . width , vid . height ) ;
}
currentplug = oldplug ;
}
2005-12-15 19:15:39 +00:00
# endif
2004-10-10 06:32:29 +00:00
2004-09-24 02:45:00 +00:00
qboolean Plugin_ExecuteString ( void )
{
2005-01-15 17:46:40 +00:00
plugin_t * oldplug = currentplug ;
2004-09-24 02:45:00 +00:00
if ( Cmd_Argc ( ) > 0 )
{
2005-01-15 17:46:40 +00:00
for ( currentplug = plugs ; currentplug ; currentplug = currentplug - > next )
2004-09-24 02:45:00 +00:00
{
2005-01-15 17:46:40 +00:00
if ( currentplug - > executestring )
2004-09-24 02:45:00 +00:00
{
2005-01-15 17:46:40 +00:00
if ( VM_Call ( currentplug - > vm , currentplug - > executestring , 0 ) )
2005-01-15 20:50:45 +00:00
{
currentplug = oldplug ;
2004-09-24 02:45:00 +00:00
return true ;
2005-01-15 20:50:45 +00:00
}
2004-09-24 02:45:00 +00:00
}
}
}
2005-01-15 17:46:40 +00:00
currentplug = oldplug ;
2004-09-24 02:45:00 +00:00
return false ;
}
2005-12-15 19:15:39 +00:00
# ifndef SERVERONLY
2005-03-10 03:55:18 +00:00
void Plug_SubConsoleCommand ( console_t * con , char * line )
{
char buffer [ 2048 ] ;
plugin_t * oldplug = currentplug ; //shouldn't really be needed, but oh well
currentplug = con - > userdata ;
Q_strncpyz ( buffer , va ( " %s %s " , con - > name , line ) , sizeof ( buffer ) ) ;
Cmd_TokenizeString ( buffer , false , false ) ;
VM_Call ( currentplug - > vm , currentplug - > conexecutecommand , 0 ) ;
currentplug = oldplug ;
}
2009-04-06 00:34:32 +00:00
void Plug_SpellCheckMaskedText ( unsigned int * maskedstring , int maskedchars , int x , int y , int cs , int firstc , int charlimit )
{
plugin_t * oldplug = currentplug ;
for ( currentplug = plugs ; currentplug ; currentplug = currentplug - > next )
{
if ( currentplug - > spellcheckmaskedtext )
{
currentplug - > inputptr = maskedstring ;
currentplug - > inputbytes = sizeof ( * maskedstring ) * maskedchars ;
VM_Call ( currentplug - > vm , currentplug - > spellcheckmaskedtext , x , y , cs , firstc , charlimit ) ;
currentplug - > inputptr = NULL ;
currentplug - > inputbytes = 0 ;
}
}
currentplug = oldplug ;
}
2005-12-15 19:15:39 +00:00
# endif
2005-03-10 03:55:18 +00:00
2005-12-15 19:15:39 +00:00
# ifndef SERVERONLY
2004-09-26 00:30:42 +00:00
qboolean Plug_Menu_Event ( int eventtype , int param ) //eventtype = draw/keydown/keyup, param = time/key
{
2005-01-15 20:50:45 +00:00
plugin_t * oc = currentplug ;
qboolean ret ;
2004-10-13 07:24:59 +00:00
extern int mousecursor_x , mousecursor_y ;
2004-09-26 00:30:42 +00:00
if ( ! menuplug )
return false ;
2005-01-15 20:50:45 +00:00
currentplug = menuplug ;
ret = VM_Call ( menuplug - > vm , menuplug - > menufunction , eventtype , param , mousecursor_x , mousecursor_y ) ;
currentplug = oc ;
return ret ;
2004-10-13 07:24:59 +00:00
}
2005-12-15 19:15:39 +00:00
# endif
# ifndef SERVERONLY
2005-08-03 23:14:59 +00:00
int Plug_ConnectionlessClientPacket ( char * buffer , int size )
{
for ( currentplug = plugs ; currentplug ; currentplug = currentplug - > next )
{
if ( currentplug - > connectionlessclientpacket )
{
switch ( VM_Call ( currentplug - > vm , currentplug - > connectionlessclientpacket , buffer , size , & net_from ) )
{
case 0 :
continue ; //wasn't handled
case 1 :
currentplug = NULL ; //was handled with no apparent result
return true ;
case 2 :
# ifndef SERVERONLY
cls . protocol = CP_PLUGIN ; //woo, the plugin wants to connect to them!
protocolclientplugin = currentplug ;
# endif
currentplug = NULL ;
return true ;
}
}
}
return false ;
}
2005-12-15 19:15:39 +00:00
# endif
# ifndef SERVERONLY
2004-10-13 07:24:59 +00:00
void Plug_SBar ( void )
{
2006-01-21 00:06:49 +00:00
extern qboolean sb_showscores , sb_showteamscores ;
2004-10-13 07:24:59 +00:00
plugin_t * oc = currentplug ;
2006-08-20 01:35:56 +00:00
int cp , ret ;
2004-10-13 07:24:59 +00:00
vrect_t rect ;
2007-02-26 03:00:25 +00:00
if ( ! Sbar_ShouldDraw ( ) )
return ;
2006-08-20 01:35:56 +00:00
ret = 0 ;
2009-11-04 21:16:50 +00:00
if ( ! plug_sbar . ival | | cl . splitclients > 1 )
2005-01-15 17:46:40 +00:00
currentplug = NULL ;
else
2004-10-13 07:24:59 +00:00
{
2005-01-15 17:46:40 +00:00
for ( currentplug = plugs ; currentplug ; currentplug = currentplug - > next )
2004-10-13 07:24:59 +00:00
{
2005-01-15 17:46:40 +00:00
if ( currentplug - > sbarlevel [ 0 ] )
{
for ( cp = 0 ; cp < cl . splitclients ; cp + + )
{ //if you don't use splitscreen, use a full videosize rect.
SCR_VRectForPlayer ( & rect , cp ) ;
2011-03-31 01:14:01 +00:00
R2D_ImageColours ( 1 , 1 , 1 , 1 ) ; // ensure menu colors are reset
2006-08-20 01:35:56 +00:00
ret | = VM_Call ( currentplug - > vm , currentplug - > sbarlevel [ 0 ] , cp , rect . x , rect . y , rect . width , rect . height , sb_showscores + sb_showteamscores * 2 ) ;
2005-01-15 17:46:40 +00:00
}
break ;
2004-10-13 07:24:59 +00:00
}
}
}
2007-02-26 03:00:25 +00:00
if ( ! ( ret & 1 ) )
2004-10-13 07:24:59 +00:00
{
Sbar_Draw ( ) ;
}
for ( currentplug = plugs ; currentplug ; currentplug = currentplug - > next )
{
if ( currentplug - > sbarlevel [ 1 ] )
{
for ( cp = 0 ; cp < cl . splitclients ; cp + + )
{ //if you don't use splitscreen, use a full videosize rect.
SCR_VRectForPlayer ( & rect , cp ) ;
2011-03-31 01:14:01 +00:00
R2D_ImageColours ( 1 , 1 , 1 , 1 ) ; // ensure menu colors are reset
2007-02-26 03:00:25 +00:00
ret | = VM_Call ( currentplug - > vm , currentplug - > sbarlevel [ 1 ] , cp , rect . x , rect . y , rect . width , rect . height , sb_showscores + sb_showteamscores * 2 ) ;
2004-10-13 07:24:59 +00:00
}
}
}
for ( currentplug = plugs ; currentplug ; currentplug = currentplug - > next )
{
if ( currentplug - > sbarlevel [ 2 ] )
{
for ( cp = 0 ; cp < cl . splitclients ; cp + + )
{ //if you don't use splitscreen, use a full videosize rect.
SCR_VRectForPlayer ( & rect , cp ) ;
2011-03-31 01:14:01 +00:00
R2D_ImageColours ( 1 , 1 , 1 , 1 ) ; // ensure menu colors are reset
2007-02-26 03:00:25 +00:00
ret | = VM_Call ( currentplug - > vm , currentplug - > sbarlevel [ 2 ] , cp , rect . x , rect . y , rect . width , rect . height , sb_showscores + sb_showteamscores * 2 ) ;
2004-10-13 07:24:59 +00:00
}
}
}
2007-02-26 03:00:25 +00:00
if ( ! ( ret & 2 ) )
{
Sbar_DrawScoreboard ( ) ;
}
2004-10-13 07:24:59 +00:00
currentplug = oc ;
2004-09-26 00:30:42 +00:00
}
2005-12-15 19:15:39 +00:00
# endif
2004-09-26 00:30:42 +00:00
2006-01-01 09:01:15 +00:00
qboolean Plug_ServerMessage ( char * buffer , int messagelevel )
2005-11-30 05:01:43 +00:00
{
2006-01-01 09:01:15 +00:00
qboolean ret = true ;
2007-02-23 00:21:33 +00:00
Cmd_TokenizeString ( buffer , false , false ) ;
Cmd_Args_Set ( buffer ) ;
2006-01-01 09:01:15 +00:00
for ( currentplug = plugs ; currentplug ; currentplug = currentplug - > next )
{
if ( currentplug - > svmsgfunction )
{
2007-02-23 00:21:33 +00:00
ret & = VM_Call ( currentplug - > vm , currentplug - > svmsgfunction , messagelevel ) ;
2006-01-01 09:01:15 +00:00
}
}
2007-02-23 00:21:33 +00:00
Cmd_Args_Set ( NULL ) ;
2006-01-01 09:01:15 +00:00
return ret ; // true to display message, false to supress
}
qboolean Plug_ChatMessage ( char * buffer , int talkernum , int tpflags )
{
qboolean ret = true ;
2007-02-23 00:21:33 +00:00
Cmd_TokenizeString ( buffer , false , false ) ;
Cmd_Args_Set ( buffer ) ;
2006-01-01 09:01:15 +00:00
for ( currentplug = plugs ; currentplug ; currentplug = currentplug - > next )
{
if ( currentplug - > chatmsgfunction )
{
2007-02-23 00:21:33 +00:00
ret & = VM_Call ( currentplug - > vm , currentplug - > chatmsgfunction , talkernum , tpflags ) ;
2006-01-01 09:01:15 +00:00
}
}
2007-02-23 00:21:33 +00:00
Cmd_Args_Set ( NULL ) ;
2006-01-01 09:01:15 +00:00
return ret ; // true to display message, false to supress
}
qboolean Plug_CenterPrintMessage ( char * buffer , int clientnum )
{
qboolean ret = true ;
2007-02-23 00:21:33 +00:00
Cmd_TokenizeString ( buffer , false , false ) ;
Cmd_Args_Set ( buffer ) ;
2005-11-30 05:01:43 +00:00
for ( currentplug = plugs ; currentplug ; currentplug = currentplug - > next )
{
2006-01-01 09:01:15 +00:00
if ( currentplug - > centerprintfunction )
2005-11-30 05:01:43 +00:00
{
2007-02-23 00:21:33 +00:00
ret & = VM_Call ( currentplug - > vm , currentplug - > centerprintfunction , clientnum ) ;
2005-11-30 05:01:43 +00:00
}
}
2007-02-23 00:21:33 +00:00
Cmd_Args_Set ( NULL ) ;
2006-01-01 09:01:15 +00:00
return ret ; // true to display message, false to supress
2005-11-30 05:01:43 +00:00
}
2004-09-24 02:45:00 +00:00
void Plug_Close ( plugin_t * plug )
{
2006-01-29 03:45:00 +00:00
if ( plug - > blockcloses )
{
Con_Printf ( " Plugin %s provides driver features, and cannot safely be unloaded \n " , plug - > name ) ;
return ;
}
2004-09-24 02:45:00 +00:00
if ( plugs = = plug )
plugs = plug - > next ;
else
{
plugin_t * prev ;
for ( prev = plugs ; prev ; prev = prev - > next )
{
if ( prev - > next = = plug )
break ;
}
if ( ! prev )
Sys_Error ( " Plug_Close: not linked \n " ) ;
prev - > next = plug - > next ;
}
2005-01-15 20:50:45 +00:00
Con_Printf ( " Closing plugin %s \n " , plug - > name ) ;
2004-09-24 02:45:00 +00:00
VM_Destroy ( plug - > vm ) ;
2005-01-15 17:46:40 +00:00
Plug_FreeConCommands ( plug ) ;
2005-12-15 19:15:39 +00:00
Plug_Client_Close ( plug ) ;
2012-07-05 19:42:36 +00:00
Z_Free ( plug ) ;
2005-12-15 19:15:39 +00:00
2005-01-15 17:46:40 +00:00
if ( currentplug = = plug )
currentplug = NULL ;
2005-01-15 20:50:45 +00:00
}
void Plug_Close_f ( void )
{
plugin_t * plug ;
char * name = Cmd_Argv ( 1 ) ;
if ( Cmd_Argc ( ) < 2 )
{
Con_Printf ( " Close which plugin? \n " ) ;
return ;
}
2007-02-23 00:21:33 +00:00
if ( currentplug )
Sys_Error ( " Plug_CloseAll_f called inside a plugin! \n " ) ;
2005-01-15 20:50:45 +00:00
for ( plug = plugs ; plug ; plug = plug - > next )
{
2005-01-24 23:47:32 +00:00
if ( ! strcmp ( plug - > name , name ) )
2005-01-15 20:50:45 +00:00
{
Plug_Close ( plug ) ;
return ;
}
}
2005-06-18 23:54:34 +00:00
name = va ( " plugins/%s " , name ) ;
for ( plug = plugs ; plug ; plug = plug - > next )
{
if ( ! strcmp ( plug - > name , name ) )
{
Plug_Close ( plug ) ;
return ;
}
}
Con_Printf ( " Plugin %s does not appear to be loaded \n " , Cmd_Argv ( 1 ) ) ;
2004-09-24 02:45:00 +00:00
}
2005-01-15 17:46:40 +00:00
void Plug_CloseAll_f ( void )
2004-09-24 02:45:00 +00:00
{
2006-02-02 01:13:52 +00:00
plugin_t * p ;
2005-01-15 17:46:40 +00:00
if ( currentplug )
Sys_Error ( " Plug_CloseAll_f called inside a plugin! \n " ) ;
while ( plugs )
{
2006-02-02 01:13:52 +00:00
p = plugs ;
while ( p - > blockcloses )
{
p = p - > next ;
if ( ! p )
return ;
}
Plug_Close ( p ) ;
2005-01-15 17:46:40 +00:00
}
}
2004-09-24 02:45:00 +00:00
2005-03-01 15:36:23 +00:00
void Plug_List_f ( void )
{
plugin_t * plug ;
for ( plug = plugs ; plug ; plug = plug - > next )
{
2005-11-30 05:01:43 +00:00
Con_Printf ( " %s - \n " , plug - > name ) ;
VM_PrintInfo ( plug - > vm ) ;
2005-03-01 15:36:23 +00:00
}
}
2005-01-15 17:46:40 +00:00
void Plug_Shutdown ( void )
{
while ( plugs )
{
2012-07-05 19:42:36 +00:00
plugs - > blockcloses = 0 ;
2005-01-15 17:46:40 +00:00
Plug_Close ( plugs ) ;
}
2012-07-05 19:42:36 +00:00
numplugbuiltins = 0 ;
BZ_Free ( plugbuiltins ) ;
plugbuiltins = NULL ;
plugincommandarraylen = 0 ;
BZ_Free ( plugincommandarray ) ;
plugincommandarray = NULL ;
2004-09-30 22:51:15 +00:00
}
# endif