Initial MSVC 2008 projects workspace
This commit is contained in:
409
l2ooghelper/bot_interaction/BotIPC.cpp
Normal file
409
l2ooghelper/bot_interaction/BotIPC.cpp
Normal file
@@ -0,0 +1,409 @@
|
||||
#include "stdafx.h"
|
||||
#include "BotIPC.h"
|
||||
#include "Logger.h"
|
||||
|
||||
|
||||
void BotInfo_Initialize( BOT_INFO *b, const wchar_t *charName, unsigned int charOid, unsigned int classId, int level )
|
||||
{
|
||||
memset( b, 0, sizeof(BOT_INFO) );
|
||||
wcsncpy( b->charName, charName, 127 ); b->charName[127] = 0;
|
||||
b->classId = classId;
|
||||
b->level = level;
|
||||
b->charOid = charOid;
|
||||
b->isMaster = b->isSlave = false;
|
||||
b->assistEnable = b->followEnable = false;
|
||||
b->processId = GetCurrentProcessId();
|
||||
}
|
||||
|
||||
LONG BotIPC_ExceptionHandler( const char *funcName, LPEXCEPTION_POINTERS ep )
|
||||
{
|
||||
log_error( LOG_ERROR, "BotIPC: ExceptionHandler invoked from function [%s]: exc: 0x%08X at 0x%p\n",
|
||||
funcName,
|
||||
ep->ExceptionRecord->ExceptionCode,
|
||||
ep->ExceptionRecord->ExceptionAddress );
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int BotIPC::s_refCount = 0;
|
||||
BotIPC *BotIPC::s_instance = NULL;
|
||||
|
||||
BotIPC *BotIPC::getInstance()
|
||||
{
|
||||
if( !BotIPC::s_instance )
|
||||
{
|
||||
BotIPC::s_instance = new BotIPC();
|
||||
BotIPC::s_refCount++;
|
||||
log_error( LOG_DEBUG, "BotIPC: instance created\n" );
|
||||
}
|
||||
return BotIPC::s_instance;
|
||||
}
|
||||
|
||||
|
||||
void BotIPC::freeInstance()
|
||||
{
|
||||
if( BotIPC::s_instance )
|
||||
{
|
||||
BotIPC::s_refCount--;
|
||||
if( BotIPC::s_refCount == 0 )
|
||||
{
|
||||
delete BotIPC::s_instance;
|
||||
BotIPC::s_instance = NULL;
|
||||
log_error( LOG_DEBUG, "BotIPC: instance deleted\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BotIPC::BotIPC()
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
log_error( LOG_DEBUG, "BotIPC: one bot info size : %u\n", sizeof(BOT_INFO) );
|
||||
log_error( LOG_DEBUG, "BotIPC: shared mem size : %u\n", sizeof(BOT_IPC_DESCRIPTOR) );
|
||||
#endif
|
||||
iAmCreator = false;
|
||||
isLocked = false;
|
||||
hMutex = hMapping = NULL;
|
||||
map = NULL;
|
||||
// try to open mutex
|
||||
hMutex = OpenMutex( SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, BOTIPC_MUTEX_NAME );
|
||||
if( !hMutex )
|
||||
{
|
||||
DWORD le = GetLastError();
|
||||
if( le != ERROR_FILE_NOT_FOUND )
|
||||
{
|
||||
log_error( LOG_ERROR, "BotIPC::BotIPC(): OpenMutex() failed: %u\n", le );
|
||||
ErrorLogger_LogLastError( "OpenMutex()", le );
|
||||
return;
|
||||
}
|
||||
log_error( LOG_DEBUG, "BotIPC::BotIPC(): mutex not exists, creating...\n" );
|
||||
hMutex = CreateMutex( NULL, FALSE, BOTIPC_MUTEX_NAME );
|
||||
if( !hMutex )
|
||||
{
|
||||
ErrorLogger_LogLastError( "CreateMutex() failed!", GetLastError() );
|
||||
return;
|
||||
}
|
||||
}
|
||||
// try to open file mapping
|
||||
hMapping = OpenFileMapping( FILE_MAP_READ | FILE_MAP_WRITE, FALSE, BOTIPC_MAPPING_NAME );
|
||||
if( !hMapping )
|
||||
{
|
||||
DWORD le = GetLastError();
|
||||
if( le != ERROR_FILE_NOT_FOUND )
|
||||
{
|
||||
log_error( LOG_ERROR, "BotIPC::BotIPC(): OpenFileMapping() failed: %u\n", le );
|
||||
ErrorLogger_LogLastError( "OpenFileMapping()", le );
|
||||
return;
|
||||
}
|
||||
log_error( LOG_DEBUG, "BotIPC::BotIPC(): file mapping not exists, creating...\n" );
|
||||
hMapping = CreateFileMapping( INVALID_HANDLE_VALUE, // page file
|
||||
NULL, PAGE_READWRITE | SEC_COMMIT, 0,
|
||||
sizeof(BOT_IPC_DESCRIPTOR), BOTIPC_MAPPING_NAME );
|
||||
if( !hMapping )
|
||||
{
|
||||
log_error( LOG_ERROR, "BotIPC::BotIPC(): CreateFileMapping() failed!\n", le );
|
||||
ErrorLogger_LogLastError( "v()", GetLastError() );
|
||||
return;
|
||||
}
|
||||
iAmCreator = true;
|
||||
}
|
||||
map = MapViewOfFile( hMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, sizeof(BOT_IPC_DESCRIPTOR) );
|
||||
if( !map )
|
||||
{
|
||||
log_error( LOG_ERROR, "BotIPC::BotIPC(): MapViewOfFile() failed!" );
|
||||
ErrorLogger_LogLastError( "MapViewOfFile()", GetLastError() );
|
||||
}
|
||||
//
|
||||
BOT_IPC_DESCRIPTOR *desc = (BOT_IPC_DESCRIPTOR *)map;
|
||||
if( iAmCreator ) // we created shmem, init it
|
||||
{
|
||||
Lock(); // lock reads/writes
|
||||
desc->dwSize = sizeof(BOT_IPC_DESCRIPTOR);
|
||||
desc->dwCreatorPid = GetCurrentProcessId();
|
||||
desc->uBotCount = 0; // no BOT_INFO structures while
|
||||
int i = 0;
|
||||
while( i<BOT_IPC_MAX_BOTS ) desc->bot[i++].charOid = 0;
|
||||
LockRelease(); // unlock
|
||||
log_error( LOG_OK, "BotIPC: created shared mem!\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error( LOG_DEBUG, "BotIPC: opened existing shared mem, creator PID: %u; number of bots: %u\n",
|
||||
desc->dwCreatorPid, desc->uBotCount );
|
||||
}
|
||||
ErrorLogger_FlushLogFile();
|
||||
}
|
||||
|
||||
|
||||
BotIPC::~BotIPC()
|
||||
{
|
||||
if( map )
|
||||
{
|
||||
if( !UnmapViewOfFile( map ) ) ErrorLogger_LogLastError( "UnmapViewOfFile()", GetLastError() );
|
||||
map = NULL;
|
||||
log_error( LOG_DEBUG, "BotIPC::~BotIPC(): shared memory view unmapped\n" );
|
||||
}
|
||||
if( hMutex )
|
||||
{
|
||||
LockRelease();
|
||||
CloseHandle( hMutex );
|
||||
hMutex = NULL;
|
||||
log_error( LOG_DEBUG, "BotIPC::~BotIPC(): mutex closed\n" );
|
||||
}
|
||||
if( hMapping )
|
||||
{
|
||||
CloseHandle( hMapping );
|
||||
hMapping = NULL;
|
||||
log_error( LOG_DEBUG, "BotIPC::~BotIPC(): mapping closed\n" );
|
||||
}
|
||||
iAmCreator = false;
|
||||
isLocked = false;
|
||||
}
|
||||
|
||||
|
||||
BOT_IPC_DESCRIPTOR *BotIPC::getDescriptor()
|
||||
{
|
||||
if( !map )
|
||||
{
|
||||
log_error( LOG_WARNING, "BotIPC::getDescriptor(): failed, because shared mem is not mapped!\n" );
|
||||
return NULL;
|
||||
}
|
||||
return (BOT_IPC_DESCRIPTOR *)map;
|
||||
}
|
||||
|
||||
|
||||
bool BotIPC::amICreator() const
|
||||
{
|
||||
return iAmCreator;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int BotIPC::addBotInfo( const BOT_INFO *b )
|
||||
{
|
||||
if( !b ) return false;
|
||||
BOT_IPC_DESCRIPTOR *d = getDescriptor();
|
||||
if( !d ) return -1;
|
||||
if( !Lock() ) return -1;
|
||||
int added_idx = -1;
|
||||
__try
|
||||
{
|
||||
if( d->uBotCount < BOT_IPC_MAX_BOTS )
|
||||
{
|
||||
// find unused bot info slot
|
||||
int i;
|
||||
for( i=0; i<BOT_IPC_MAX_BOTS; i++ ) if( d->bot[i].charOid == 0 ) { added_idx = i; break; }
|
||||
if( added_idx == -1 )
|
||||
{
|
||||
log_error( LOG_ERROR, "BotIPC::addBotInfo(): ERROR: cannot find free slot to add!\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy( (void *)&(d->bot[added_idx]), (const void *)b, sizeof(BOT_INFO) );
|
||||
d->uBotCount++; // new one bot added
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error( LOG_ERROR, "BotIPC::addBotInfo(): failed beacuse mex bot count (%d) reached!\n", BOT_IPC_MAX_BOTS );
|
||||
}
|
||||
}
|
||||
__except( BotIPC_ExceptionHandler( "addBotInfo()", GetExceptionInformation() ) ) {}
|
||||
LockRelease();
|
||||
return added_idx;
|
||||
}
|
||||
|
||||
|
||||
bool BotIPC::getBotInfo( int index, BOT_INFO *b )
|
||||
{
|
||||
if( !b ) return false;
|
||||
if( index<0 || index>=BOT_IPC_MAX_BOTS )
|
||||
{
|
||||
log_error( LOG_ERROR, "BotIPC::getBotInfo( index = %d ): invalid index\n", index );
|
||||
return false;
|
||||
}
|
||||
BOT_IPC_DESCRIPTOR *d = getDescriptor();
|
||||
if( !d )
|
||||
{
|
||||
log_error( LOG_ERROR, "BotIPC::getBotInfo( index = %d ): shared mem not mapped!\n", index );
|
||||
return false;
|
||||
}
|
||||
if( !Lock() ) return false;
|
||||
__try
|
||||
{
|
||||
BOT_INFO *src = &(d->bot[index]);
|
||||
memcpy( (void *)b, (const void *)src, sizeof(BOT_INFO) );
|
||||
}
|
||||
__except( BotIPC_ExceptionHandler( "getBotInfo()", GetExceptionInformation() ) ) {}
|
||||
LockRelease();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool BotIPC::setBotInfo( int index, const BOT_INFO *b )
|
||||
{
|
||||
if( !b ) return false;
|
||||
if( index<0 || index>=BOT_IPC_MAX_BOTS )
|
||||
{
|
||||
log_error( LOG_ERROR, "BotIPC::setBotInfo(): invalid index %d\n", index );
|
||||
return false;
|
||||
}
|
||||
BOT_IPC_DESCRIPTOR *d = getDescriptor();
|
||||
if( !d )
|
||||
{
|
||||
log_error( LOG_ERROR, "BotIPC::setBotInfo(): shared mem not mapped!\n" );
|
||||
return false;
|
||||
}
|
||||
if( !Lock() ) return false;
|
||||
__try
|
||||
{
|
||||
BOT_INFO *dst = &(d->bot[index]);
|
||||
memcpy( (void *)dst, (const void *)b, sizeof(BOT_INFO) );
|
||||
}
|
||||
__except( BotIPC_ExceptionHandler( "setBotInfo()", GetExceptionInformation() ) ) {}
|
||||
LockRelease();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool BotIPC::delBot( int index )
|
||||
{
|
||||
if( index<0 || index>=BOT_IPC_MAX_BOTS )
|
||||
{
|
||||
log_error( LOG_ERROR, "BotIPC::delBot( int index = %d ): invalid index\n", index );
|
||||
return false;
|
||||
}
|
||||
BOT_IPC_DESCRIPTOR *d = getDescriptor();
|
||||
if( !d )
|
||||
{
|
||||
log_error( LOG_ERROR, "BotIPC::delBot(): shared mem not mapped!\n" );
|
||||
return false;
|
||||
}
|
||||
if( !Lock() ) return false;
|
||||
bool ret = false;
|
||||
__try
|
||||
{
|
||||
if( d->bot[index].charOid > 0 )
|
||||
{
|
||||
d->bot[index].charOid = 0;
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = true;
|
||||
log_error( LOG_WARNING, "BotIPC::delBot( %d ): charOid is already 0!\n", index );
|
||||
}
|
||||
}
|
||||
__except( BotIPC_ExceptionHandler( "delBot()", GetExceptionInformation() ) ) {}
|
||||
LockRelease();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void BotIPC::delAllMyProcessBots()
|
||||
{
|
||||
log_error( LOG_DEBUG, "BotIPC::delAllMyProcessBots(): start\n" );
|
||||
BOT_IPC_DESCRIPTOR *d = getDescriptor();
|
||||
if( !d )
|
||||
{
|
||||
log_error( LOG_ERROR, "BotIPC::delAllMyProcessBots(): shared mem not mapped!\n" );
|
||||
return;
|
||||
}
|
||||
if( !Lock() )
|
||||
{
|
||||
log_error( LOG_ERROR, "BotIPC::delAllMyProcessBots(): Lock failed!\n" );
|
||||
ErrorLogger_FlushLogFile();
|
||||
return;
|
||||
}
|
||||
int index = 0;
|
||||
unsigned int myPid = GetCurrentProcessId();
|
||||
int nFreed = 0;
|
||||
__try
|
||||
{
|
||||
for( index=0; index<BOT_IPC_MAX_BOTS; index++ )
|
||||
{
|
||||
if( d->bot[index].processId == myPid )
|
||||
{
|
||||
d->bot[index].charOid = 0;
|
||||
nFreed++;
|
||||
log_error( LOG_DEBUG, "BotIPC::delAllMyProcessBots(): deleted bot index %d\n", index );
|
||||
}
|
||||
}
|
||||
}
|
||||
__except( BotIPC_ExceptionHandler( "delAllMyProcessBots()", GetExceptionInformation() ) ) {}
|
||||
LockRelease();
|
||||
log_error( LOG_DEBUG, "BotIPC::delAllMyProcessBots(): deleted %d my bots\n", nFreed );
|
||||
}
|
||||
|
||||
void BotIPC::dumpToLog()
|
||||
{
|
||||
BOT_IPC_DESCRIPTOR *d = getDescriptor();
|
||||
if( !d ) return;
|
||||
if( !Lock() ) return;
|
||||
__try
|
||||
{
|
||||
int idx;
|
||||
log_error( LOG_DEBUG, "===== BotIPC::dumpToLog() =====\n" );
|
||||
for( idx = 0; idx < BOT_IPC_MAX_BOTS; idx++ )
|
||||
{
|
||||
if( d->bot[idx].charOid > 0 )
|
||||
{
|
||||
log_error( LOG_DEBUG, "Bot %d: char: %S lvl %d (class %d %s) [isSlave: %d] [isMaster: %d]\n",
|
||||
idx, d->bot[idx].charName, d->bot[idx].level, d->bot[idx].classId,
|
||||
L2Data_getClass( d->bot[idx].classId ),
|
||||
(int)d->bot[idx].isSlave, (int)d->bot[idx].isMaster );
|
||||
}
|
||||
}
|
||||
log_error( LOG_DEBUG, "===== BotIPC::dumpToLog() END =====\n" );
|
||||
}
|
||||
__except( BotIPC_ExceptionHandler( "dumpToLog()", GetExceptionInformation() ) ) {}
|
||||
LockRelease();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool BotIPC::Lock()
|
||||
{
|
||||
if( !hMutex ) return false;
|
||||
if( isLocked ) return true;
|
||||
DWORD wait_res = WaitForSingleObject( hMutex, 1000 );
|
||||
if( wait_res == WAIT_OBJECT_0 )
|
||||
{
|
||||
isLocked = true;
|
||||
return true;
|
||||
}
|
||||
// error handle
|
||||
DWORD le = GetLastError();
|
||||
log_error( LOG_ERROR, "BotIPC lock failed!!! possible fatal error, may need restarting all radars/bots!\n" );
|
||||
switch( wait_res )
|
||||
{
|
||||
case WAIT_TIMEOUT: log_error( LOG_ERROR, "BotIPC lock: wait_res: WAIT_TIMEOUT!\n" ); break;
|
||||
case WAIT_ABANDONED:
|
||||
{
|
||||
log_error( LOG_ERROR, "BotIPC lock: wait res: WAIT_TIMEOUT!\n" );
|
||||
// but in this case we own mutex
|
||||
log_error( LOG_WARNING, "Mutex wait abandoned, but now we own mutex... all OK\n" );
|
||||
isLocked = true;
|
||||
return true;
|
||||
} break;
|
||||
default: log_error( LOG_ERROR, "BotIPC lock: wait res: unk %u!\n", wait_res ); break;
|
||||
}
|
||||
ErrorLogger_LogLastError( "BotIPC lock: last error was: ", le );
|
||||
return false;
|
||||
}
|
||||
|
||||
void BotIPC::LockRelease()
|
||||
{
|
||||
if( !hMutex ) return;
|
||||
if( !isLocked ) return;
|
||||
if( !ReleaseMutex( hMutex ) )
|
||||
{
|
||||
log_error( LOG_WARNING, "BotIPC::LockRelease(): ReleaseMutex failed (not owner?)\n" );
|
||||
ErrorLogger_LogLastError( "ReleaseMutex()", GetLastError() );
|
||||
}
|
||||
isLocked = false;
|
||||
}
|
||||
|
Reference in New Issue
Block a user