2007-11-04 03:53:53 +00:00
/*
2012-03-17 20:01:54 +00:00
Copyright ( c ) 2001 , Loki software , inc .
All rights reserved .
Redistribution and use in source and binary forms , with or without modification ,
are permitted provided that the following conditions are met :
Redistributions of source code must retain the above copyright notice , this list
of conditions and the following disclaimer .
Redistributions in binary form must reproduce the above copyright notice , this
list of conditions and the following disclaimer in the documentation and / or
other materials provided with the distribution .
Neither the name of Loki software nor the names of its contributors may be used
to endorse or promote products derived from this software without specific prior
written permission .
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ` ` AS IS ' '
AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED . IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES
( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ;
LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*/
2007-11-04 03:53:53 +00:00
//-----------------------------------------------------------------------------
//
// DESCRIPTION:
// monitoring window for running BSP processes (and possibly various other stuff)
# include "stdafx.h"
# include "watchbsp.h"
# include "feedback.h"
# ifdef _WIN32
# include <winsock2.h>
# endif
2017-08-30 11:07:42 +00:00
# if defined( __linux__ ) || defined( __FreeBSD__ ) || defined( __APPLE__ )
2007-11-04 03:53:53 +00:00
# include <sys/time.h>
# define SOCKET_ERROR -1
# endif
# ifdef __APPLE__
# include <unistd.h>
# endif
# include <assert.h>
2017-03-16 11:40:56 +00:00
# include <glib/gi18n.h>
2007-11-04 03:53:53 +00:00
// Static functions for the SAX callbacks -------------------------------------------------------
// utility for saxStartElement below
2012-03-17 20:01:54 +00:00
static void abortStream ( message_info_t * data ) {
g_pParentWnd - > GetWatchBSP ( ) - > Reset ( ) ;
// tell there has been an error
if ( g_pParentWnd - > GetWatchBSP ( ) - > HasBSPPlugin ( ) ) {
g_BSPFrontendTable . m_pfnEndListen ( 2 ) ;
}
// yeah this doesn't look good.. but it's needed so that everything will be ignored until the stream goes out
data - > ignore_depth = - 1 ;
data - > recurse + + ;
2007-11-04 03:53:53 +00:00
}
# include "stream_version.h"
2012-03-17 20:01:54 +00:00
static void saxStartElement ( message_info_t * data , const xmlChar * name , const xmlChar * * attrs ) {
if ( data - > ignore_depth = = 0 ) {
if ( data - > bGeometry ) {
// we have a handler
data - > pGeometry - > saxStartElement ( data , name , attrs ) ;
}
else
{
if ( strcmp ( ( char * ) name , " q3map_feedback " ) = = 0 ) {
// check the correct version
// old q3map don't send a version attribute
// the ones we support .. send Q3MAP_STREAM_VERSION
if ( ! attrs [ 0 ] | | ! attrs [ 1 ] | | ( strcmp ( ( char * ) attrs [ 0 ] , " version " ) ! = 0 ) ) {
Sys_FPrintf ( SYS_ERR , " No stream version given in the feedback stream, this is an old q3map version. \n "
" Please turn off monitored compiling if you still wish to use this q3map executable \n " ) ;
abortStream ( data ) ;
return ;
}
else if ( strcmp ( ( char * ) attrs [ 1 ] , Q3MAP_STREAM_VERSION ) ! = 0 ) {
Sys_FPrintf ( SYS_ERR ,
" This version of Radiant reads version %s debug streams, I got an incoming connection with version %s \n "
" Please make sure your versions of Radiant and q3map are matching. \n " , Q3MAP_STREAM_VERSION , ( char * ) attrs [ 1 ] ) ;
abortStream ( data ) ;
return ;
}
}
// we don't treat locally
else if ( strcmp ( ( char * ) name , " message " ) = = 0 ) {
data - > msg_level = atoi ( ( char * ) attrs [ 1 ] ) ;
}
else if ( strcmp ( ( char * ) name , " polyline " ) = = 0 ) {
// polyline has a particular status .. right now we only use it for leakfile ..
data - > bGeometry = true ;
data - > pGeometry = & g_pointfile ;
data - > pGeometry - > saxStartElement ( data , name , attrs ) ;
}
else if ( strcmp ( ( char * ) name , " select " ) = = 0 ) {
CSelectMsg * pSelect = new CSelectMsg ( ) ;
data - > bGeometry = true ;
data - > pGeometry = pSelect ;
data - > pGeometry - > saxStartElement ( data , name , attrs ) ;
}
else if ( strcmp ( ( char * ) name , " pointmsg " ) = = 0 ) {
CPointMsg * pPoint = new CPointMsg ( ) ;
data - > bGeometry = true ;
data - > pGeometry = pPoint ;
data - > pGeometry - > saxStartElement ( data , name , attrs ) ;
}
else if ( strcmp ( ( char * ) name , " windingmsg " ) = = 0 ) {
CWindingMsg * pWinding = new CWindingMsg ( ) ;
data - > bGeometry = true ;
data - > pGeometry = pWinding ;
data - > pGeometry - > saxStartElement ( data , name , attrs ) ;
}
else
{
Sys_FPrintf ( SYS_WRN , " WARNING: ignoring unrecognized node in XML stream (%s) \n " , name ) ;
// we don't recognize this node, jump over it
// (NOTE: the ignore mechanism is a bit screwed, only works when starting an ignore at the highest level)
data - > ignore_depth = data - > recurse ;
}
}
}
data - > recurse + + ;
2007-11-04 03:53:53 +00:00
}
2012-03-17 20:01:54 +00:00
static void saxEndElement ( message_info_t * data , const xmlChar * name ) {
2007-11-04 03:59:18 +00:00
data - > recurse - - ;
// we are out of an ignored chunk
if ( data - > recurse = = data - > ignore_depth ) {
data - > ignore_depth = 0 ;
return ;
}
if ( data - > bGeometry ) {
data - > pGeometry - > saxEndElement ( data , name ) ;
// we add the object to the debug window
if ( ! data - > bGeometry ) {
g_DbgDlg . Push ( data - > pGeometry ) ;
}
}
if ( data - > recurse = = data - > stop_depth ) {
2007-11-04 03:53:53 +00:00
# ifdef _DEBUG
2016-05-16 19:20:20 +00:00
Sys_FPrintf ( SYS_ERR , " ERROR: Received error msg .. shutting down.. \n " ) ;
2007-11-04 03:53:53 +00:00
# endif
2007-11-04 03:59:18 +00:00
// tell there has been an error
if ( g_pParentWnd - > GetWatchBSP ( ) - > HasBSPPlugin ( ) ) {
g_BSPFrontendTable . m_pfnEndListen ( 2 ) ;
}
return ;
}
2007-11-04 03:53:53 +00:00
}
2012-03-17 20:01:54 +00:00
static void saxCharacters ( message_info_t * data , const xmlChar * ch , int len ) {
if ( data - > bGeometry ) {
data - > pGeometry - > saxCharacters ( data , ch , len ) ;
}
else
{
if ( data - > ignore_depth ! = 0 ) {
return ;
}
// output the message using the level
char buf [ 1024 ] ;
memcpy ( buf , ch , len ) ;
buf [ len ] = ' \0 ' ;
Sys_FPrintf ( data - > msg_level , " %s " , buf ) ;
// if this message has error level flag, we mark the depth to stop the compilation when we get out
// we don't set the msg level if we don't stop on leak
if ( data - > msg_level = = 3 ) {
data - > stop_depth = data - > recurse - 1 ;
}
}
2007-11-04 03:53:53 +00:00
}
2012-03-17 20:01:54 +00:00
static void saxComment ( void * ctx , const xmlChar * msg ) {
Sys_Printf ( " XML comment: %s \n " , msg ) ;
2007-11-04 03:53:53 +00:00
}
2012-03-17 20:01:54 +00:00
static void saxWarning ( void * ctx , const char * msg , . . . ) {
char saxMsgBuffer [ 4096 ] ;
va_list args ;
2008-07-05 10:21:36 +00:00
2012-03-17 20:01:54 +00:00
va_start ( args , msg ) ;
vsprintf ( saxMsgBuffer , msg , args ) ;
va_end ( args ) ;
Sys_FPrintf ( SYS_WRN , " XML warning: %s \n " , saxMsgBuffer ) ;
2007-11-04 03:53:53 +00:00
}
2012-03-17 20:01:54 +00:00
static void saxError ( void * ctx , const char * msg , . . . ) {
char saxMsgBuffer [ 4096 ] ;
va_list args ;
2008-07-05 10:21:36 +00:00
2012-03-17 20:01:54 +00:00
va_start ( args , msg ) ;
vsprintf ( saxMsgBuffer , msg , args ) ;
va_end ( args ) ;
Sys_FPrintf ( SYS_ERR , " XML error: %s \n " , saxMsgBuffer ) ;
2007-11-04 03:53:53 +00:00
}
2012-03-17 20:01:54 +00:00
static void saxFatal ( void * ctx , const char * msg , . . . ) {
char buffer [ 4096 ] ;
2008-07-05 10:21:36 +00:00
2012-03-17 20:01:54 +00:00
va_list args ;
2008-07-05 10:21:36 +00:00
2012-03-17 20:01:54 +00:00
va_start ( args , msg ) ;
vsprintf ( buffer , msg , args ) ;
va_end ( args ) ;
Sys_FPrintf ( SYS_ERR , " XML fatal error: %s \n " , buffer ) ;
2007-11-04 03:53:53 +00:00
}
static xmlSAXHandler saxParser = {
2012-03-17 20:01:54 +00:00
0 , /* internalSubset */
0 , /* isStandalone */
0 , /* hasInternalSubset */
0 , /* hasExternalSubset */
0 , /* resolveEntity */
0 , /* getEntity */
0 , /* entityDecl */
0 , /* notationDecl */
0 , /* attributeDecl */
0 , /* elementDecl */
0 , /* unparsedEntityDecl */
0 , /* setDocumentLocator */
0 , /* startDocument */
0 , /* endDocument */
( startElementSAXFunc ) saxStartElement , /* startElement */
( endElementSAXFunc ) saxEndElement , /* endElement */
0 , /* reference */
( charactersSAXFunc ) saxCharacters , /* characters */
0 , /* ignorableWhitespace */
0 , /* processingInstruction */
( commentSAXFunc ) saxComment , /* comment */
( warningSAXFunc ) saxWarning , /* warning */
( errorSAXFunc ) saxError , /* error */
( fatalErrorSAXFunc ) saxFatal , /* fatalError */
2007-11-04 03:53:53 +00:00
} ;
// ------------------------------------------------------------------------------------------------
2012-03-17 20:01:54 +00:00
CWatchBSP : : ~ CWatchBSP ( ) {
2013-11-20 02:15:06 +00:00
2012-03-17 20:01:54 +00:00
Reset ( ) ;
2013-11-20 02:15:06 +00:00
if ( m_pCmd ) {
g_ptr_array_free ( m_pCmd , true ) ;
m_pCmd = NULL ;
}
2012-03-17 20:01:54 +00:00
if ( m_sBSPName ) {
2013-11-20 02:15:06 +00:00
g_free ( m_sBSPName ) ;
2012-03-17 20:01:54 +00:00
m_sBSPName = NULL ;
}
2013-11-20 02:15:06 +00:00
2012-03-17 20:01:54 +00:00
Net_Shutdown ( ) ;
2007-11-04 03:53:53 +00:00
}
2013-11-20 02:15:06 +00:00
void CWatchBSP : : RunQuake ( ) {
// build the command line
Str cmd ;
cmd = g_pGameDescription - > mExecutablesPath . GetBuffer ( ) ;
// this is game dependant
if ( ! strcmp ( ValueForKey ( g_qeglobals . d_project_entity , " gamemode " ) , " mp " ) ) {
// MP
cmd + = g_pGameDescription - > mMultiplayerEngine . GetBuffer ( ) ;
}
else
{
// SP
cmd + = g_pGameDescription - > mEngine . GetBuffer ( ) ;
}
# ifdef _WIN32
// NOTE: we are using unix pathnames and CreateProcess doesn't like / in the program path
// FIXME: This isn't true anymore, doesn't it?
FindReplace ( cmd , " / " , " \\ " ) ;
# endif
Str cmdline ;
if ( g_pGameDescription - > idTech2 ) {
cmdline = " +exec radiant.cfg +map " ;
cmdline + = m_sBSPName ;
}
else
// NOTE: idTech3 specific - there used to be some logic depending on engine breed here
{
cmdline = " +set sv_pure 0 " ;
// TTimo: a check for vm_* but that's all fine
//cmdline = "+set sv_pure 0 +set vm_ui 0 +set vm_cgame 0 +set vm_game 0 ";
if ( * ValueForKey ( g_qeglobals . d_project_entity , " gamename " ) ! = ' \0 ' ) {
cmdline + = " +set fs_game " ;
cmdline + = ValueForKey ( g_qeglobals . d_project_entity , " gamename " ) ;
cmdline + = " " ;
}
//!\todo Read the start-map args from a config file.
if ( g_pGameDescription - > mGameFile = = " wolf.game " ) {
if ( ! strcmp ( ValueForKey ( g_qeglobals . d_project_entity , " gamemode " ) , " mp " ) ) {
// MP
cmdline + = " +devmap " ;
cmdline + = m_sBSPName ;
}
else
{
// SP
cmdline + = " +set nextmap \" spdevmap " ;
cmdline + = m_sBSPName ;
cmdline + = " \" " ;
}
}
else
{
cmdline + = " +devmap " ;
cmdline + = m_sBSPName ;
}
}
Sys_Printf ( " %s %s \n " , cmd . GetBuffer ( ) , cmdline . GetBuffer ( ) ) ;
// execute now
if ( ! Q_Exec ( cmd . GetBuffer ( ) , ( char * ) cmdline . GetBuffer ( ) , g_pGameDescription - > mEnginePath . GetBuffer ( ) , false ) ) {
CString msg ;
msg = " Failed to execute the following command: " ;
msg + = cmd ; msg + = cmdline ;
Sys_Printf ( msg ) ;
2017-03-16 11:40:56 +00:00
gtk_MessageBox ( g_pParentWnd - > m_pWidget , msg , _ ( " BSP monitoring " ) , MB_OK | MB_ICONERROR ) ;
2013-11-20 02:15:06 +00:00
}
}
2012-03-17 20:01:54 +00:00
void CWatchBSP : : Reset ( ) {
if ( m_pInSocket ) {
Net_Disconnect ( m_pInSocket ) ;
m_pInSocket = NULL ;
}
if ( m_pListenSocket ) {
Net_Disconnect ( m_pListenSocket ) ;
m_pListenSocket = NULL ;
}
if ( m_xmlInputBuffer ) {
xmlFreeParserInputBuffer ( m_xmlInputBuffer ) ;
m_xmlInputBuffer = NULL ;
}
2013-11-20 02:15:06 +00:00
if ( m_xmlParserCtxt ) {
xmlFreeParserCtxt ( m_xmlParserCtxt ) ;
m_xmlParserCtxt = NULL ;
}
2012-03-17 20:01:54 +00:00
m_eState = EIdle ;
2007-11-04 03:53:53 +00:00
}
2012-03-17 20:01:54 +00:00
bool CWatchBSP : : SetupListening ( ) {
2007-11-04 03:53:53 +00:00
# ifdef _DEBUG
2012-03-17 20:01:54 +00:00
if ( m_pListenSocket ) {
2016-05-16 19:20:20 +00:00
Sys_FPrintf ( SYS_ERR , " ERROR: m_pListenSocket != NULL in CWatchBSP::SetupListening \n " ) ;
2012-03-17 20:01:54 +00:00
return false ;
}
2007-11-04 03:53:53 +00:00
# endif
2012-03-17 20:01:54 +00:00
Sys_Printf ( " Setting up \n " ) ;
if ( ! Net_Setup ( ) ) {
return false ;
}
2008-04-14 20:15:34 +00:00
2012-03-17 20:01:54 +00:00
m_pListenSocket = Net_ListenSocket ( 39000 ) ;
if ( m_pListenSocket = = NULL ) {
return false ;
}
2008-04-14 20:15:34 +00:00
2012-03-17 20:01:54 +00:00
Sys_Printf ( " Listening... \n " ) ;
return true ;
2007-11-04 03:53:53 +00:00
}
2007-11-04 03:59:18 +00:00
void CWatchBSP : : DoEBeginStep ( ) {
2013-11-20 02:15:06 +00:00
2007-11-04 03:59:18 +00:00
if ( ! SetupListening ( ) ) {
CString msg ;
2017-03-16 11:40:56 +00:00
msg = _ ( " Failed to get a listening socket on port 39000. \n Try running with BSP monitoring disabled if you can't fix this. \n " ) ;
2007-11-04 03:59:18 +00:00
Sys_Printf ( msg ) ;
2017-03-16 11:40:56 +00:00
gtk_MessageBox ( g_pParentWnd - > m_pWidget , msg , _ ( " BSP monitoring " ) , MB_OK | MB_ICONERROR ) ;
2013-11-20 02:15:06 +00:00
Reset ( ) ;
2007-11-04 03:59:18 +00:00
return ;
}
2013-11-20 02:15:06 +00:00
// re-initialise the debug window
if ( m_iCurrentStep = = 0 ) {
g_DbgDlg . Init ( ) ;
}
2007-11-04 03:59:18 +00:00
// set the timer for timeouts and step cancellation
g_timer_reset ( m_pTimer ) ;
g_timer_start ( m_pTimer ) ;
2007-11-04 03:53:53 +00:00
2007-11-04 03:59:18 +00:00
if ( ! m_bBSPPlugin ) {
Sys_Printf ( " === running BSP command === \n %s \n " , g_ptr_array_index ( m_pCmd , m_iCurrentStep ) ) ;
2013-11-20 02:15:06 +00:00
if ( ! Q_Exec ( NULL , ( char * ) g_ptr_array_index ( m_pCmd , m_iCurrentStep ) , NULL , true ) ) {
2007-11-04 03:59:18 +00:00
CString msg ;
2017-03-16 11:40:56 +00:00
msg = _ ( " Failed to execute the following command: " ) ;
2013-11-20 02:15:06 +00:00
msg + = ( char * ) g_ptr_array_index ( m_pCmd , m_iCurrentStep ) ;
2017-03-16 11:40:56 +00:00
msg + = _ ( " \n Check that the file exists and that you don't run out of system resources. \n " ) ;
2007-11-04 03:59:18 +00:00
Sys_Printf ( msg ) ;
2017-03-16 11:40:56 +00:00
gtk_MessageBox ( g_pParentWnd - > m_pWidget , msg , _ ( " BSP monitoring " ) , MB_OK | MB_ICONERROR ) ;
2013-11-20 02:15:06 +00:00
Reset ( ) ;
2007-11-04 03:59:18 +00:00
return ;
}
2013-11-20 02:15:06 +00:00
2007-11-04 03:59:18 +00:00
}
2013-11-20 02:15:06 +00:00
2007-11-04 03:59:18 +00:00
m_eState = EBeginStep ;
2007-11-04 03:53:53 +00:00
}
2012-03-17 20:01:54 +00:00
void CWatchBSP : : RoutineProcessing ( ) {
// used for select()
2007-11-04 03:53:53 +00:00
# ifdef _WIN32
2012-03-17 20:01:54 +00:00
TIMEVAL tout = { 0 , 0 } ;
2007-11-04 03:53:53 +00:00
# endif
2017-08-30 11:07:42 +00:00
# if defined( __linux__ ) || defined( __FreeBSD__ ) || defined( __APPLE__ )
2012-03-17 20:01:54 +00:00
timeval tout ;
tout . tv_sec = 0 ;
tout . tv_usec = 0 ;
2007-11-04 03:53:53 +00:00
# endif
2012-03-17 20:01:54 +00:00
switch ( m_eState )
{
case EBeginStep :
// timeout: if we don't get an incoming connection fast enough, go back to idle
if ( g_timer_elapsed ( m_pTimer , NULL ) > g_PrefsDlg . m_iTimeout ) {
2017-03-16 11:40:56 +00:00
gtk_MessageBox ( g_pParentWnd - > m_pWidget , _ ( " The connection timed out, assuming the BSP process failed \n Make sure you are using a networked version of Q3Map? \n Otherwise you need to disable BSP Monitoring in prefs. " ) , _ ( " BSP process monitoring " ) , MB_OK ) ;
2012-03-17 20:01:54 +00:00
Reset ( ) ;
if ( m_bBSPPlugin ) {
// status == 1 : didn't get the connection
g_BSPFrontendTable . m_pfnEndListen ( 1 ) ;
}
2013-11-20 02:15:06 +00:00
break ;
2012-03-17 20:01:54 +00:00
}
2007-11-04 03:53:53 +00:00
# ifdef _DEBUG
2012-03-17 20:01:54 +00:00
// some debug checks
if ( ! m_pListenSocket ) {
2016-05-16 19:20:20 +00:00
Sys_FPrintf ( SYS_ERR , " ERROR: m_pListenSocket == NULL in CWatchBSP::RoutineProcessing EBeginStep state \n " ) ;
2013-11-20 02:15:06 +00:00
Reset ( ) ;
break ;
2012-03-17 20:01:54 +00:00
}
2007-11-04 03:53:53 +00:00
# endif
2012-03-17 20:01:54 +00:00
// we are not connected yet, accept any incoming connection
m_pInSocket = Net_Accept ( m_pListenSocket ) ;
if ( m_pInSocket ) {
Sys_Printf ( " Connected. \n " ) ;
// prepare the message info struct for diving in
memset ( & m_message_info , 0 , sizeof ( message_info_s ) ) ;
// a dumb flag to make sure we init the push parser context when first getting a msg
m_eState = EWatching ;
}
break ;
2013-11-20 02:15:06 +00:00
2012-03-17 20:01:54 +00:00
case EWatching :
2007-11-04 03:53:53 +00:00
# ifdef _DEBUG
2012-03-17 20:01:54 +00:00
// some debug checks
if ( ! m_pInSocket ) {
2016-05-16 19:20:20 +00:00
Sys_FPrintf ( SYS_ERR , " ERROR: m_pInSocket == NULL in CWatchBSP::RoutineProcessing EWatching state \n " ) ;
2013-11-20 02:15:06 +00:00
Reset ( ) ;
break ;
2012-03-17 20:01:54 +00:00
}
2007-11-04 03:53:53 +00:00
# endif
2012-03-17 20:01:54 +00:00
// select() will identify if the socket needs an update
// if the socket is identified that means there's either a message or the connection has been closed/reset/terminated
fd_set readfds ;
int ret ;
FD_ZERO ( & readfds ) ;
FD_SET ( ( ( unsigned int ) m_pInSocket - > socket ) , & readfds ) ;
2007-11-04 03:53:53 +00:00
// from select man page:
// n is the highest-numbered descriptor in any of the three sets, plus 1
// (no use on windows)
2012-03-17 20:01:54 +00:00
ret = select ( m_pInSocket - > socket + 1 , & readfds , NULL , NULL , & tout ) ;
if ( ret = = SOCKET_ERROR ) {
2016-05-16 19:20:20 +00:00
Sys_FPrintf ( SYS_WRN , " WARNING: SOCKET_ERROR in CWatchBSP::RoutineProcessing \n " ) ;
2012-03-17 20:01:54 +00:00
Sys_Printf ( " Terminating the connection. \n " ) ;
Reset ( ) ;
2013-11-20 02:15:06 +00:00
break ;
2012-03-17 20:01:54 +00:00
}
if ( ret = = 1 ) {
// the socket has been identified, there's something (message or disconnection)
// see if there's anything in input
ret = Net_Receive ( m_pInSocket , & msg ) ;
if ( ret > 0 ) {
// unsigned int size = msg.size; //++timo just a check
2013-11-20 02:15:06 +00:00
g_strlcpy ( m_xmlBuf , NMSG_ReadString ( & msg ) , sizeof ( m_xmlBuf ) ) ;
if ( m_xmlParserCtxt = = NULL ) {
2012-03-17 20:01:54 +00:00
m_xmlParserCtxt = xmlCreatePushParserCtxt ( & saxParser , & m_message_info , m_xmlBuf , strlen ( m_xmlBuf ) , NULL ) ;
if ( m_xmlParserCtxt = = NULL ) {
Sys_FPrintf ( SYS_ERR , " Failed to create the XML parser (incoming stream began with: %s) \n " , m_xmlBuf ) ;
Reset ( ) ;
2013-11-20 02:15:06 +00:00
break ;
2012-03-17 20:01:54 +00:00
}
}
else
{
xmlParseChunk ( m_xmlParserCtxt , m_xmlBuf , strlen ( m_xmlBuf ) , 0 ) ;
}
}
else
{
// error or connection closed/reset
// NOTE: if we get an error down the XML stream we don't reach here
Net_Disconnect ( m_pInSocket ) ;
m_pInSocket = NULL ;
Sys_Printf ( " Connection closed. \n " ) ;
if ( m_bBSPPlugin ) {
// let the BSP plugin know that the job is done
g_BSPFrontendTable . m_pfnEndListen ( 0 ) ;
}
2013-11-20 02:15:06 +00:00
Reset ( ) ;
2012-03-17 20:01:54 +00:00
// move to next step or finish
m_iCurrentStep + + ;
if ( m_iCurrentStep < m_pCmd - > len ) {
DoEBeginStep ( ) ;
2013-11-20 02:15:06 +00:00
break ;
2012-03-17 20:01:54 +00:00
}
2013-11-20 02:15:06 +00:00
// launch the engine .. OMG
if ( g_PrefsDlg . m_bRunQuake ) {
// do we enter sleep mode before?
if ( g_PrefsDlg . m_bDoSleep ) {
Sys_Printf ( " Going into sleep mode.. \n " ) ;
g_pParentWnd - > OnSleep ( ) ;
2012-03-17 20:01:54 +00:00
}
2013-11-20 02:15:06 +00:00
Sys_Printf ( " Running engine... \n " ) ;
RunQuake ( ) ;
2012-03-17 20:01:54 +00:00
}
}
}
break ;
default :
break ;
}
2007-11-04 03:53:53 +00:00
}
2012-03-17 20:01:54 +00:00
void CWatchBSP : : DoMonitoringLoop ( GPtrArray * pCmd , char * sBSPName ) {
2013-11-20 02:15:06 +00:00
guint i ;
2012-03-17 20:01:54 +00:00
if ( m_eState ! = EIdle ) {
Sys_Printf ( " WatchBSP got a monitoring request while not idling... \n " ) ;
// prompt the user, should we cancel the current process and go ahead?
2017-03-16 11:40:56 +00:00
if ( gtk_MessageBox ( g_pParentWnd - > m_pWidget , _ ( " I am already monitoring a BSP process. \n Do you want me to override and start a new compilation? " ) ,
_ ( " BSP process monitoring " ) , MB_YESNO ) = = IDNO ) {
2013-11-20 02:15:06 +00:00
return ;
2012-03-17 20:01:54 +00:00
}
}
2013-11-20 02:15:06 +00:00
Reset ( ) ;
if ( m_pCmd ) {
g_ptr_array_free ( m_pCmd , true ) ;
m_pCmd = NULL ;
}
if ( m_sBSPName ) {
g_free ( m_sBSPName ) ;
m_sBSPName = NULL ;
}
2013-11-20 20:21:58 +00:00
// glib 2.30
// m_pCmd = g_ptr_array_new_full( pCmd->len, g_free );
m_pCmd = g_ptr_array_sized_new ( pCmd - > len ) ;
g_ptr_array_set_free_func ( m_pCmd , g_free ) ;
2013-11-20 02:15:06 +00:00
for ( i = 0 ; i < pCmd - > len ; i + + ) {
g_ptr_array_add ( m_pCmd , g_strdup ( ( char * ) pCmd - > pdata [ i ] ) ) ;
}
2012-03-17 20:01:54 +00:00
m_iCurrentStep = 0 ;
2013-11-20 02:15:06 +00:00
m_sBSPName = g_strdup ( sBSPName ) ;
2012-03-17 20:01:54 +00:00
DoEBeginStep ( ) ;
2007-11-04 03:53:53 +00:00
}
2012-03-17 20:01:54 +00:00
void CWatchBSP : : ExternalListen ( ) {
m_bBSPPlugin = true ;
DoEBeginStep ( ) ;
2007-11-04 03:53:53 +00:00
}
// the part of the watchbsp interface we export to plugins
// NOTE: in the long run, the whole watchbsp.cpp interface needs to go out and be handled at the BSP plugin level
// for now we provide something really basic and limited, the essential is to have something that works fine and fast (for 1.1 final)
2012-03-17 20:01:54 +00:00
void WINAPI QERApp_Listen ( ) {
// open the listening socket
g_pParentWnd - > GetWatchBSP ( ) - > ExternalListen ( ) ;
2007-11-04 03:53:53 +00:00
}