static void NativeModuleHost_Destroy(MODULE_HANDLE moduleHandle) { if (moduleHandle != NULL) { MODULE_HOST* module_host = (MODULE_HOST*)moduleHandle; if (module_host->module != NULL) { const MODULE_LOADER* module_loader = module_host->module_loader; MODULE_LIBRARY_HANDLE module_library = module_host->module_library_handle; if (module_loader != NULL) { MODULE_LOADER_API * loader_api = module_loader->api; if ((module_library != NULL) && (loader_api != NULL)) { const MODULE_API* module_apis = loader_api->GetApi(module_loader, module_library); if (MODULE_DESTROY(module_apis) != NULL) { /*Codes_SRS_NATIVEMODULEHOST_17_028: [ NativeModuleHost_Destroy shall free all remaining allocated resources if moduleHandle is not NULL. ]*/ MODULE_DESTROY(module_apis)(module_host->module); } loader_api->Unload(module_loader, module_library); } } module_host->module = NULL; module_host->module_library_handle = NULL; module_host->module_host_broker = NULL; free(module_host); } } /*Codes_SRS_NATIVEMODULEHOST_17_027: [ NativeModuleHost_Destroy shall always destroy the module loader. ]*/ ModuleLoader_Destroy(); }
static MODULE_HANDLE NativeModuleHost_Create(BROKER_HANDLE broker, const void* configuration) { MODULE_HOST * result; if (broker == NULL || configuration == NULL) { /*Codes_SRS_NATIVEMODULEHOST_17_008: [ NativeModuleHost_Create shall return NULL if broker is NULL. ]*/ /*Codes_SRS_NATIVEMODULEHOST_17_009: [ NativeModuleHost_Create shall return NULL if configuration does not contain valid JSON. ]*/ LogError("broker [%p] or configuration [%p] is NULL, both are required", broker, configuration); result = NULL; } else { /*Codes_SRS_NATIVEMODULEHOST_17_010: [ NativeModuleHost_Create shall intialize the Module_Loader. ]*/ if (ModuleLoader_Initialize() != MODULE_LOADER_SUCCESS) { /*Codes_SRS_NATIVEMODULEHOST_17_026: [ If any step above fails, then NativeModuleHost_Create shall free all resources allocated and return NULL. ]*/ LogError("ModuleLoader_Initialize failed"); result = NULL; } else { /*Codes_SRS_NATIVEMODULEHOST_17_011: [ NativeModuleHost_Create shall parse the configuration JSON. ]*/ char * outprocess_module_args = (char *)configuration; JSON_Value *root_value = json_parse_string(outprocess_module_args); JSON_Object * module_host_args; if ((root_value == NULL) || ((module_host_args = json_value_get_object(root_value)) == NULL)) { if (root_value != NULL) { json_value_free(root_value); } LogError("NativeModuleHost_Create could not parse arguments as JSON"); result = NULL; } else { /*Codes_SRS_NATIVEMODULEHOST_17_035: [ If the "outprocess.loaders" array exists in the configuration JSON, NativeModuleHost_Create shall initialize the Module_Loader from this array. ]*/ JSON_Value * loaders_array = json_object_get_value(module_host_args, OOP_MODULE_LOADERS_ARRAY_KEY); if ((loaders_array != NULL) && (ModuleLoader_InitializeFromJson(loaders_array) != MODULE_LOADER_SUCCESS)) { LogError("NativeModuleHost_Create could not extract loaders array from module arguments."); result = NULL; } else { /*Codes_SRS_NATIVEMODULEHOST_17_012: [ NativeModuleHost_Create shall get the "outprocess.loader" object from the configuration JSON. ]*/ JSON_Object * loader_args = json_object_get_object(module_host_args, OOP_MODULE_LOADER_KEY); if (loader_args == NULL) { LogError("NativeModuleHost_Create could not get loader arguments."); result = NULL; } else { GATEWAY_MODULE_LOADER_INFO loader_info; if (parse_loader(loader_args, &loader_info) != 0) { /*Codes_SRS_NATIVEMODULEHOST_17_026: [ If any step above fails, then NativeModuleHost_Create shall free all resources allocated and return NULL. ]*/ LogError("NativeModuleHost_Create could not extract loader information from loader arguments."); result = NULL; } else { // Have loader and entrypoint now, get module. result = (MODULE_HOST*)malloc(sizeof(MODULE_HOST)); if (result == NULL) { LogError("NativeModuleHost_Create could not allocate module."); result = NULL; } else { /*Codes_SRS_NATIVEMODULEHOST_17_018: [ NativeModuleHost_Create shall get the "module.args" object from the configuration JSON. ]*/ JSON_Value * module_args = json_object_get_value(module_host_args, OOP_MODULE_ARGS_KEY); char * module_args_string = json_serialize_to_string(module_args); if (module_create(result, broker, &loader_info, module_args_string) != 0) { /*Codes_SRS_NATIVEMODULEHOST_17_026: [ If any step above fails, then NativeModuleHost_Create shall free all resources allocated and return NULL. ]*/ LogError("NativeModuleHost_Create could not load module."); free(result); result = NULL; } /*Codes_SRS_NATIVEMODULEHOST_17_024: [ NativeModuleHost_Create shall free all resources used during module loading. ]*/ json_free_serialized_string(module_args_string); } loader_info.loader->api->FreeEntrypoint(loader_info.loader, loader_info.entrypoint); } } } /*Codes_SRS_NATIVEMODULEHOST_17_024: [ NativeModuleHost_Create shall free all resources used during module loading. ]*/ json_value_free(root_value); } if (result == NULL) { // failed to create a module, give up entirely. /*Codes_SRS_NATIVEMODULEHOST_17_026: [ If any step above fails, then NativeModuleHost_Create shall free all resources allocated and return NULL. ]*/ ModuleLoader_Destroy(); } } } return result; }
MODULE_LOADER_RESULT ModuleLoader_Initialize(void) { MODULE_LOADER_RESULT result; /*Codes_SRS_MODULE_LOADER_13_001: [ ModuleLoader_Initialize shall initialize g_module_loader.lock. ]*/ g_module_loaders.lock = Lock_Init(); if (g_module_loaders.lock == NULL) { LogError("Lock_Init failed"); /*Codes_SRS_MODULE_LOADER_13_002: [ ModuleLoader_Initialize shall return MODULE_LOADER_ERROR if an underlying platform call fails. ]*/ result = MODULE_LOADER_ERROR; } else { /*Codes_SRS_MODULE_LOADER_13_003: [ ModuleLoader_Initialize shall acquire the lock on g_module_loader.lock. ]*/ if (Lock(g_module_loaders.lock) != LOCK_OK) { LogError("Lock failed"); Lock_Deinit(g_module_loaders.lock); g_module_loaders.lock = NULL; /*Codes_SRS_MODULE_LOADER_13_002: [ ModuleLoader_Initialize shall return MODULE_LOADER_ERROR if an underlying platform call fails. ]*/ result = MODULE_LOADER_ERROR; } else { /*Codes_SRS_MODULE_LOADER_13_004: [ ModuleLoader_Initialize shall initialize g_module.module_loaders by calling VECTOR_create. ]*/ g_module_loaders.module_loaders = VECTOR_create(sizeof(MODULE_LOADER*)); if (g_module_loaders.module_loaders == NULL) { LogError("VECTOR_create failed"); Unlock(g_module_loaders.lock); Lock_Deinit(g_module_loaders.lock); g_module_loaders.lock = NULL; /*Codes_SRS_MODULE_LOADER_13_002: [ ModuleLoader_Initialize shall return MODULE_LOADER_ERROR if an underlying platform call fails. ]*/ result = MODULE_LOADER_ERROR; } else { // add all supported module loaders const MODULE_LOADER* supported_loaders[] = { DynamicLoader_Get() #ifdef NODE_BINDING_ENABLED , NodeLoader_Get() #endif #ifdef JAVA_BINDING_ENABLED , JavaLoader_Get() #endif #ifdef DOTNET_BINDING_ENABLED , DotnetLoader_Get() #endif #ifdef DOTNET_CORE_BINDING_ENABLED , DotnetCoreLoader_Get() #endif }; size_t loaders_count = sizeof(supported_loaders) / sizeof(supported_loaders[0]); size_t i; for (i = 0; i < loaders_count; i++) { /*Codes_SRS_MODULE_LOADER_13_005: [ ModuleLoader_Initialize shall add the default support module loaders to g_module.module_loaders. ]*/ if (add_module_loader(supported_loaders[i]) != MODULE_LOADER_SUCCESS) { LogError("Could not add loader - %s", supported_loaders[i]->name); break; } } /*Codes_SRS_MODULE_LOADER_13_007: [ ModuleLoader_Initialize shall unlock g_module.lock. ]*/ Unlock(g_module_loaders.lock); // adding loaders failed if we bailed early from the loop above if (i < loaders_count) { ModuleLoader_Destroy(); /*Codes_SRS_MODULE_LOADER_13_002: [ ModuleLoader_Initialize shall return MODULE_LOADER_ERROR if an underlying platform call fails. ]*/ result = MODULE_LOADER_ERROR; } else { /*Codes_SRS_MODULE_LOADER_13_006: [ ModuleLoader_Initialize shall return MODULE_LOADER_SUCCESS once all the default loaders have been added successfully. ]*/ result = MODULE_LOADER_SUCCESS; } } } } return result; }