RBOOL rpHostCommonPlatformLib_stop ( ) { if( 0 == rInterlocked_decrement32( &g_hcpContext.isRunning ) ) { stopBeacons(); stopAllModules(); rpal_memory_free( g_hcpContext.primaryUrl ); rpal_memory_free( g_hcpContext.secondaryUrl ); if( NULL != g_hcpContext.enrollmentToken && 0 != g_hcpContext.enrollmentTokenSize ) { rpal_memory_free( g_hcpContext.enrollmentToken ); } freeKeys(); #ifdef RPAL_PLATFORM_WINDOWS SetConsoleCtrlHandler( (PHANDLER_ROUTINE)ctrlHandler, FALSE ); #endif rMutex_free( g_hcpContext.cloudConnectionMutex ); rEvent_free( g_hcpContext.isCloudOnline ); g_hcpContext.cloudConnectionMutex = NULL; g_hcpContext.isCloudOnline = NULL; rpal_Context_cleanup(); rpal_Context_deinitialize(); // If the default crashContext is still present, remove it since // we are shutting down properly. If it's non-default leave it since // somehow we may have had a higher order crash we want to keep // track of but we are still leaving through our normal code path. if( 1 == getCrashContextSize() ) { rpal_debug_info( "clearing default crash context" ); cleanCrashContext(); } } else { rInterlocked_increment32( &g_hcpContext.isRunning ); } rpal_debug_info( "finished stopping hcp" ); return TRUE; }
RPRIVATE RU32 RPAL_THREAD_FUNC thread_quitAndCleanup ( RPVOID context ) { UNREFERENCED_PARAMETER( context ); if( 0 == rInterlocked_decrement32( &g_hcpContext.isRunning ) ) { rpal_thread_sleep( MSEC_FROM_SEC( 1 ) ); stopAllModules(); stopBeacons(); if( NULL != g_hcpContext.enrollmentToken && 0 != g_hcpContext.enrollmentTokenSize ) { rpal_memory_free( g_hcpContext.enrollmentToken ); } // If the default crashContext is still present, remove it since // we are shutting down properly. If it's non-default leave it since // somehow we may have had a higher order crash we want to keep // track of but we are still leaving through our normal code path. if( 1 == getCrashContextSize() ) { cleanCrashContext(); } rpal_Context_cleanup(); rpal_Context_deinitialize(); } else { rInterlocked_increment32( &g_hcpContext.isRunning ); } return 0; }
RBOOL rEvent_wait ( rEvent ev, RU32 timeout ) { RBOOL isSuccess = FALSE; _rEvent* volatile evt = (_rEvent*)ev; if( rpal_memory_isValid( ev ) ) { #ifdef RPAL_PLATFORM_WINDOWS rInterlocked_increment32( &evt->waitCount ); if( WAIT_OBJECT_0 == WaitForSingleObject( evt->hEvent, timeout ) ) { isSuccess = TRUE; } rInterlocked_decrement32( &evt->waitCount ); #elif defined( RPAL_PLATFORM_LINUX ) || defined( RPAL_PLATFORM_MACOSX ) struct timespec abs_time; struct timeval cur_time; struct timezone ts; int err = 0; gettimeofday( &cur_time, &ts ); abs_time.tv_sec = cur_time.tv_sec; abs_time.tv_nsec = cur_time.tv_usec * 1000; abs_time.tv_sec += ( timeout / 1000 ); abs_time.tv_nsec += ( ( timeout % 1000 ) * 1000000 ); if( abs_time.tv_nsec >= 1000000000 ) { abs_time.tv_sec += ( abs_time.tv_nsec / 1000000000 ); abs_time.tv_nsec = abs_time.tv_nsec % 1000000000; } if( 0 == pthread_mutex_lock( &evt->hMutex ) ) { if( evt->isOn ) { if( !evt->isManualReset ) { evt->isOn = FALSE; } isSuccess = TRUE; } else { // This is extremely convoluted and unintuitive... what else did you expect since // it turns out a _wait can wakeup randomly because "signals" without letting you // know. So we need to wrap the entire thing in a loop and manually look for a flag. while( 0 == err && !evt->isOn ) { if( RINFINITE != timeout ) { err = pthread_cond_timedwait( &evt->hCond, &evt->hMutex, &abs_time ); } else { err = pthread_cond_wait( &evt->hCond, &evt->hMutex ); } } if( evt->isOn ) { if( !evt->isManualReset ) { evt->isOn = FALSE; } isSuccess = TRUE; } } pthread_mutex_unlock( &evt->hMutex ); } #endif } return isSuccess; }
RBOOL rpHostCommonPlatformLib_launch ( RU8 configHint, RPNCHAR primaryHomeUrl, RPNCHAR secondaryHomeUrl ) { RBOOL isInitSuccessful = FALSE; rSequence staticConfig = NULL; RPCHAR tmpStr = NULL; rSequence tmpSeq = NULL; RPU8 tmpBuffer = NULL; RU32 tmpSize = 0; RU16 tmpPort = 0; rpal_debug_info( "launching hcp" ); #ifdef RPAL_PLATFORM_WINDOWS if( setGlobalCrashHandler() && SetConsoleCtrlHandler( (PHANDLER_ROUTINE)ctrlHandler, TRUE ) ) { rpal_debug_info( "global crash handler set" ); } else { rpal_debug_warning( "error setting global crash handler" ); } #endif if( 1 == rInterlocked_increment32( &g_hcpContext.isRunning ) ) { if( rpal_initialize( NULL, RPAL_COMPONENT_HCP ) ) { CryptoLib_init(); if( NULL == ( g_hcpContext.cloudConnectionMutex = rMutex_create() ) || NULL == ( g_hcpContext.isCloudOnline = rEvent_create( TRUE ) ) ) { rMutex_free( g_hcpContext.cloudConnectionMutex ); rpal_debug_error( "could not create cloud connection mutex or event" ); return FALSE; } g_hcpContext.currentId.raw = g_idTemplate.raw; // We attempt to load some initial config from the serialized // rSequence that can be patched in this binary. if( NULL != ( staticConfig = getStaticConfig() ) ) { if( rSequence_getSTRINGA( staticConfig, RP_TAGS_HCP_PRIMARY_URL, &tmpStr ) && rSequence_getRU16( staticConfig, RP_TAGS_HCP_PRIMARY_PORT, &tmpPort ) ) { g_hcpContext.primaryUrl = rpal_string_strdupA( tmpStr ); g_hcpContext.primaryPort = tmpPort; rpal_debug_info( "loading primary url from static config" ); } if( rSequence_getSTRINGA( staticConfig, RP_TAGS_HCP_SECONDARY_URL, &tmpStr ) && rSequence_getRU16( staticConfig, RP_TAGS_HCP_SECONDARY_PORT, &tmpPort ) ) { g_hcpContext.secondaryUrl = rpal_string_strdupA( tmpStr ); g_hcpContext.secondaryPort = tmpPort; rpal_debug_info( "loading secondary url from static config" ); } if( rSequence_getSEQUENCE( staticConfig, RP_TAGS_HCP_ID, &tmpSeq ) ) { g_hcpContext.currentId = seqToHcpId( tmpSeq ); rpal_debug_info( "loading default id from static config" ); } if( rSequence_getBUFFER( staticConfig, RP_TAGS_HCP_C2_PUBLIC_KEY, &tmpBuffer, &tmpSize ) ) { setC2PublicKey( rpal_memory_duplicate( tmpBuffer, tmpSize ) ); rpal_debug_info( "loading c2 public key from static config" ); } if( rSequence_getBUFFER( staticConfig, RP_TAGS_HCP_ROOT_PUBLIC_KEY, &tmpBuffer, &tmpSize ) ) { setRootPublicKey( rpal_memory_duplicate( tmpBuffer, tmpSize ) ); rpal_debug_info( "loading root public key from static config" ); } if( rSequence_getSTRINGA( staticConfig, RP_TAGS_HCP_DEPLOYMENT_KEY, &tmpStr ) ) { g_hcpContext.deploymentKey = rpal_string_strdupA( tmpStr ); rpal_debug_info( "loading deployment key from static config" ); } rSequence_free( staticConfig ); } // Now we will override the defaults (if present) with command // line parameters. if( NULL != primaryHomeUrl && 0 != rpal_string_strlen( primaryHomeUrl ) ) { if( NULL != g_hcpContext.primaryUrl ) { rpal_memory_free( g_hcpContext.primaryUrl ); g_hcpContext.primaryUrl = NULL; } g_hcpContext.primaryUrl = rpal_string_ntoa( primaryHomeUrl ); } if( NULL != secondaryHomeUrl && 0 != rpal_string_strlen( secondaryHomeUrl ) ) { if( NULL != g_hcpContext.secondaryUrl ) { rpal_memory_free( g_hcpContext.secondaryUrl ); g_hcpContext.secondaryUrl = NULL; } g_hcpContext.secondaryUrl = rpal_string_ntoa( secondaryHomeUrl ); } g_hcpContext.enrollmentToken = NULL; g_hcpContext.enrollmentTokenSize = 0; getStoreConf(); /* Sets the agent ID platform. */ // Set the current configId g_hcpContext.currentId.id.configId = configHint; if( startBeacons() ) { isInitSuccessful = TRUE; } else { rpal_debug_warning( "error starting beacons" ); } CryptoLib_deinit(); } else { rpal_debug_warning( "hcp platform could not init rpal" ); } } else { rInterlocked_decrement32( &g_hcpContext.isRunning ); rpal_debug_info( "hcp already launched" ); } return isInitSuccessful; }
RBOOL rpal_initialize ( rpal_PContext context, RU32 logicalIdentifier ) { RBOOL isSuccess = FALSE; rpal_private_module_context* tmpContext = NULL; rHandle hCurrentModule = RPAL_HANDLE_INIT; g_rpal_localContext.identifier = logicalIdentifier; rpal_srand( (RU32)rpal_time_getLocal() ); if( NULL == context ) { #ifdef RPAL_MODE_MASTER if( NULL == g_rpal_context ) { g_rpal_context = malloc( sizeof( *g_rpal_context ) ); if( NULL != g_rpal_context ) { g_rpal_is_root_context = TRUE; g_rpal_context->version = RPAL_VERSION_CURRENT; #ifdef RPAL_PLATFORM_WINDOWS g_heap = HeapCreate( 0, ( 1024 * 1024 * 10 ), 0 ); #endif // This is the core library. // Setup the Memory Management RPAL_API_REF( rpal_memory_allocEx ) = _rpal_memory_allocEx; RPAL_API_REF( rpal_memory_free ) = _rpal_memory_free; RPAL_API_REF( rpal_memory_isValid ) = _rpal_memory_isValid; RPAL_API_REF( rpal_memory_realloc ) = _rpal_memory_realloc; RPAL_API_REF( rpal_memory_totalUsed ) = _rpal_memory_totalUsed; RPAL_API_REF( rpal_time_getGlobal ) = _rpal_time_getGlobal; RPAL_API_REF( rpal_time_setGlobalOffset ) = _rpal_time_setGlobalOffset; RPAL_API_REF( rpal_handleManager_create_global ) = _rpal_handleManager_create_global; RPAL_API_REF( rpal_handleManager_open_global ) = _rpal_handleManager_open_global; RPAL_API_REF( rpal_handleManager_openEx_global ) = _rpal_handleManager_openEx_global; RPAL_API_REF( rpal_handleManager_close_global ) = _rpal_handleManager_close_global; RPAL_API_REF( rpal_handleManager_getValue_global ) = _rpal_handleManager_getValue_global; #ifdef RPAL_FEATURE_MEMORY_ACCOUNTING RPAL_API_REF( rpal_memory_printDetailedUsage ) = _rpal_memory_printDetailedUsage; #endif if( NULL != ( g_handleMajorLock = rRwLock_create() ) ) { rInterlocked_increment32( &g_rpal_nrecursiveInit ); isSuccess = TRUE; } else { free( g_rpal_context ); g_rpal_context = NULL; } } } else { rInterlocked_increment32( &g_rpal_nrecursiveInit ); isSuccess = TRUE; } #endif } #ifdef RPAL_MODE_SLAVE else if( RPAL_VERSION_CURRENT <= context->version ) { // We bind this instance to the core. g_rpal_context = context; isSuccess = TRUE; } #endif if( isSuccess ) { // If the local_handles is already create it means that // someone local already initialised rpal so no need to proceed... if( NULL == g_rpal_localContext.local_handles ) { // Let's setup the local context g_rpal_localContext.local_handles = rpal_btree_create( sizeof( rHandle ), (rpal_btree_comp_f)_findHandle, NULL ); if( NULL == g_rpal_localContext.local_handles ) { isSuccess = FALSE; } else { hCurrentModule.info.major = RPAL_HANDLES_MAJOR_MODULECONTEXT; hCurrentModule.info.minor = logicalIdentifier; // Let's register our local context // Is our component registered? if( rpal_handleManager_open( hCurrentModule, (RPVOID)&tmpContext ) ) { // Seems our component is registered, is it just a double-registration // or is it a different instance? if( tmpContext != &g_rpal_localContext ) { // Different instance, this is bad, bail out! isSuccess = FALSE; } else { // Double init... all good, ignore. } // Either way, release the handle rpal_handleManager_close( hCurrentModule, NULL ); } else { // Our component is not registered, do it. hCurrentModule = rpal_handleManager_create( RPAL_HANDLES_MAJOR_MODULECONTEXT, logicalIdentifier, &g_rpal_localContext, NULL ); if( RPAL_HANDLE_INVALID == hCurrentModule.h ) { // There was an error registering, bail out. isSuccess = FALSE; } else { g_rpal_localContext.hModule.h = hCurrentModule.h; } } } if( !isSuccess ) { if( NULL != g_rpal_localContext.local_handles ) { rpal_btree_destroy( g_rpal_localContext.local_handles, FALSE ); } if( g_rpal_is_root_context ) { free( g_rpal_context ); g_rpal_context = NULL; g_rpal_is_root_context = FALSE; } } } #ifdef RPAL_MODE_MASTER if( !isSuccess && g_rpal_is_root_context ) { rRwLock_free( g_handleMajorLock ); free( g_rpal_context ); g_rpal_context = NULL; } #endif } return isSuccess; }