library/src/dynamic_modules/BP-DynamicModules.cc
// All application wide dynamic loads are stored in the GHT only.  They are tracked and
// monitored via the GHT only.  The reason this routine takes a json module
// config and not a JSON string is so that you as a developer can attach json
// data which may have been created dynamically to the JSON structure without
// having to do a lot of sprintf() conversion nonsense.  You can just add JSON nodes by
// lookup path query instead. (BP_JSONAddNodeByPathQuery/BP_JSONAddTableByPathQuery)
All application wide dynamic loads are stored in the GHT only.  They are tracked and
monitored via the GHT only.  The reason this routine takes a json module
config and not a JSON string is so that you as a developer can attach json
data which may have been created dynamically to the JSON structure without
having to do a lot of sprintf() conversion nonsense.  You can just add JSON nodes by
lookup path query instead.
All application wide dynamic loads are stored in the GHT only . They are tracked and monitored via the GHT only . The reason this routine takes a json module config and not a JSON string is so that you as a developer can attach json data which may have been created dynamically to the JSON structure without having to do a lot of sprintf () conversion nonsense . You can just add JSON nodes by lookup path query instead .
BP_ERROR_T BP_LoadDynamicModulesByParsedJSON
(
	P_BP_DYNAMIC_MODULE_LOAD_HOOKS load_hooks,
	P_BP_JSON                      module_config
)
{
	if(!load_hooks)
		return ERR_FAILURE;
	if(!load_hooks->event_manager)
		return ERR_FAILURE;
	if(!load_hooks->httpd_session)
		return ERR_FAILURE;
	if(!module_config)
		return ERR_FAILURE;
	if(!module_config->json_out_hreg)
		return ERR_FAILURE;
	if(!module_config->json_out_hreg->hive)
		return ERR_FAILURE;
	if(!module_config->json_out_hreg->hive->data)
		return ERR_FAILURE;
	BP_HashRegDisplay(&global_hash_table_registry, BP_FALSE, BP_TRUE);
	BP_DYNAMIC_MODULE tmp_module;
	BP_ZERO_STACK(tmp_module);
	BP_HASH_ITER_OPEN((P_BP_HTKE) module_config->json_out_hreg->hive->data, current_module_iter)
	{
		BP_ZERO_STACK(tmp_module);
		if(current_module_iter->type != BP_HASH_TABLE_KEYED_ENTRY_TYPE_NAMED_HASH_TABLE)
			continue;
		if(!BP_StringIsReasonablePrintableString(current_module_iter->key, bpstrlen(current_module_iter->key), BP_FALSE, BP_FALSE))
			continue;
		P_BP_HTKE parent = (P_BP_HTKE) current_module_iter->parent;
		if(!parent)
			continue;
		char *mod_path[] =
		{
				parent->key,
				current_module_iter->key,
				NULL
		};
		char * current_module_table_path = BP_HashRegPathArrayToStringLookup((char **) &mod_path);
		P_BP_HTKE enabled         = BP_HashRegLookupTableEntryByDataKeyIndexAndTablePathQuery(module_config->json_out_hreg, current_module_table_path, "enabled");
		P_BP_HTKE so_path         = BP_HashRegLookupTableEntryByDataKeyIndexAndTablePathQuery(module_config->json_out_hreg, current_module_table_path, "so_path");
		P_BP_HTKE dev_description = BP_HashRegLookupTableEntryByDataKeyIndexAndTablePathQuery(module_config->json_out_hreg, current_module_table_path, "dev_description");
		P_BP_HTKE dev_notes       = BP_HashRegLookupTableEntryByDataKeyIndexAndTablePathQuery(module_config->json_out_hreg, current_module_table_path, "dev_notes");
		if(!enabled)
		{
			bpfree(current_module_table_path);
			continue;
		}
		if(!so_path)
		{
			bpfree(current_module_table_path);
			continue;
		}
		if(!dev_description)
		{
			bpfree(current_module_table_path);
			continue;
		}
		if(!dev_notes)
		{
			bpfree(current_module_table_path);
			continue;
		}
		if(enabled->type != BP_HASH_TABLE_KEYED_ENTRY_TYPE_UTF8_STRING)
		{
			bpfree(current_module_table_path);
			continue;
		}
		if(so_path->type != BP_HASH_TABLE_KEYED_ENTRY_TYPE_UTF8_STRING)
		{
			bpfree(current_module_table_path);
			continue;
		}
		if(dev_description->type != BP_HASH_TABLE_KEYED_ENTRY_TYPE_UTF8_STRING)
		{
			bpfree(current_module_table_path);
			continue;
		}
		if(dev_notes->type != BP_HASH_TABLE_KEYED_ENTRY_TYPE_UTF8_STRING)
		{
			bpfree(current_module_table_path);
			continue;
		}
		printf("\n Getting here too!?: %s - %p - %p - %p -%p",current_module_table_path,  enabled, so_path, dev_description, dev_notes);
		BP_HASH_TABLE_ENTER_CRITICAL_SECTION(NULL);
		printf("\n Attempting to load module: (%s) %s", (char *) so_path->data, (char *) current_module_iter->key);
		char so_sha1[50];
		BP_ZERO_STACK(so_sha1);
		BP_FileSHA1Contents((char *) so_path->data, (char *) &so_sha1);
		if
		(
			bpstrlen((char *) &so_sha1) &&
			BP_FileAtPathExistsAndIsExecutable((char *) so_path->data) == ERR_SUCCESS
		)
		{
			void * so_handle = dlopen((char *) so_path->data, RTLD_NOW|RTLD_GLOBAL);
			if(so_handle)
			{
				printf("\n DLOPEN REPORTED THAT LIBRARY OPENED OK!: %p - %p", &global_hash_table_registry, so_handle);
				char **mod_config_from_lib = (char **) dlsym(so_handle, "global_mod_init_config_json");
				if(mod_config_from_lib)
				{
					if(mod_config_from_lib[0])
					{
						if(BP_StringIsReasonablePrintableString(mod_config_from_lib[0], bpstrlen(mod_config_from_lib[0]), BP_TRUE, BP_TRUE))
						{
							P_BP_JSON mod_json = BP_JSONCreate();
							if(BP_JSONParseFromBuffer(mod_json, mod_config_from_lib[0], bpstrlen(mod_config_from_lib[0]), 100, 100))
							{
								BP_JSONDisplay(mod_json);
								BP_JSONFinalizeOutput(mod_json);
								BP_JSONDisplay(mod_json);
								tmp_module.so_module_name                 = current_module_iter->key;
								tmp_module.so_handle                      = so_handle;
								tmp_module.so_module_config_json          = mod_config_from_lib[0];
								tmp_module.so_module_load_path            = (char *) so_path->data;
								tmp_module.so_module_filesystem_sha1_hash = (char *) &so_sha1;
								if(!BP_DynamicModuleLoadIntoGHT((P_BP_DYNAMIC_MODULE) &tmp_module))
									printf("\n [!!] The dynamic module '%s' Could not be loaded into the process space due to one or more errors (dynamic loader has failed)", tmp_module.so_module_name);
							}
							else
							{
								printf("\n [!!] The dynamic module '%s' failed to load due to being unable to parse module configuration data from global module symbol lookup (JSON examined is within the module itself, not within this app).", tmp_module.so_module_name);
							}
							if(mod_json)
								BP_JSONDestroy(mod_json);
						}
					}
				}
			}
		}
		BP_HASH_TABLE_LEAVE_CRITICAL_SECTION(NULL);
		P_BP_HTKE extra_data_table = BP_HashRegLookupTableEntryByDataKeyIndexAndTablePathQuery(module_config->json_out_hreg, current_module_table_path, "extra_data");
		if(current_module_table_path)
			bpfree(current_module_table_path);
		%%%%%%%%%%%%%%
		%%%%%%%%%%%%%%
		if(!tmp_module.loaded_ok)
		{
			printf("\n [!!] Module load failed for %s", tmp_module.so_module_name);
			return ERR_FAILURE;
		}
	}
	BP_HASH_ITER_CLOSE;
	return ERR_SUCCESS;
}
BP_ERROR_T BP_LoadDynamicModulesByParsedJSON ( P_BP_DYNAMIC_MODULE_LOAD_HOOKS load_hooks , P_BP_JSON module_config ) { if ( ! load_hooks ) return ERR_FAILURE ; if ( ! load_hooks -> event_manager ) return ERR_FAILURE ; if ( ! load_hooks -> httpd_session ) return ERR_FAILURE ; if ( ! module_config ) return ERR_FAILURE ; if ( ! module_config -> json_out_hreg ) return ERR_FAILURE ; if ( ! module_config -> json_out_hreg -> hive ) return ERR_FAILURE ; if ( ! module_config -> json_out_hreg -> hive -> data ) return ERR_FAILURE ; BP_HashRegDisplay ( & global_hash_table_registry , BP_FALSE , BP_TRUE ) ; BP_DYNAMIC_MODULE tmp_module ; BP_ZERO_STACK ( tmp_module ) ; BP_HASH_ITER_OPEN ( ( P_BP_HTKE ) module_config -> json_out_hreg -> hive -> data , current_module_iter ) { BP_ZERO_STACK ( tmp_module ) ; if ( current_module_iter -> type != BP_HASH_TABLE_KEYED_ENTRY_TYPE_NAMED_HASH_TABLE ) continue ; if ( ! BP_StringIsReasonablePrintableString ( current_module_iter -> key , bpstrlen ( current_module_iter -> key ) , BP_FALSE , BP_FALSE ) ) continue ; P_BP_HTKE parent = ( P_BP_HTKE ) current_module_iter -> parent ; if ( ! parent ) continue ; char * mod_path [ ] = { parent -> key , current_module_iter -> key , NULL } ; char * current_module_table_path = BP_HashRegPathArrayToStringLookup ( ( char * * ) & mod_path ) ; P_BP_HTKE enabled = BP_HashRegLookupTableEntryByDataKeyIndexAndTablePathQuery ( module_config -> json_out_hreg , current_module_table_path , " " ) ; P_BP_HTKE so_path = BP_HashRegLookupTableEntryByDataKeyIndexAndTablePathQuery ( module_config -> json_out_hreg , current_module_table_path , " " ) ; P_BP_HTKE dev_description = BP_HashRegLookupTableEntryByDataKeyIndexAndTablePathQuery ( module_config -> json_out_hreg , current_module_table_path , " " ) ; P_BP_HTKE dev_notes = BP_HashRegLookupTableEntryByDataKeyIndexAndTablePathQuery ( module_config -> json_out_hreg , current_module_table_path , " " ) ; if ( ! enabled ) { bpfree ( current_module_table_path ) ; continue ; } if ( ! so_path ) { bpfree ( current_module_table_path ) ; continue ; } if ( ! dev_description ) { bpfree ( current_module_table_path ) ; continue ; } if ( ! dev_notes ) { bpfree ( current_module_table_path ) ; continue ; } if ( enabled -> type != BP_HASH_TABLE_KEYED_ENTRY_TYPE_UTF8_STRING ) { bpfree ( current_module_table_path ) ; continue ; } if ( so_path -> type != BP_HASH_TABLE_KEYED_ENTRY_TYPE_UTF8_STRING ) { bpfree ( current_module_table_path ) ; continue ; } if ( dev_description -> type != BP_HASH_TABLE_KEYED_ENTRY_TYPE_UTF8_STRING ) { bpfree ( current_module_table_path ) ; continue ; } if ( dev_notes -> type != BP_HASH_TABLE_KEYED_ENTRY_TYPE_UTF8_STRING ) { bpfree ( current_module_table_path ) ; continue ; } printf ( " \n " , current_module_table_path , enabled , so_path , dev_description , dev_notes ) ; BP_HASH_TABLE_ENTER_CRITICAL_SECTION ( NULL ) ; printf ( " \n " , ( char * ) so_path -> data , ( char * ) current_module_iter -> key ) ; char so_sha1 [ 50 ] ; BP_ZERO_STACK ( so_sha1 ) ; BP_FileSHA1Contents ( ( char * ) so_path -> data , ( char * ) & so_sha1 ) ; if ( bpstrlen ( ( char * ) & so_sha1 ) && BP_FileAtPathExistsAndIsExecutable ( ( char * ) so_path -> data ) == ERR_SUCCESS ) { void * so_handle = dlopen ( ( char * ) so_path -> data , RTLD_NOW | RTLD_GLOBAL ) ; if ( so_handle ) { printf ( " \n " , & global_hash_table_registry , so_handle ) ; char * * mod_config_from_lib = ( char * * ) dlsym ( so_handle , " " ) ; if ( mod_config_from_lib ) { if ( mod_config_from_lib [ 0 ] ) { if ( BP_StringIsReasonablePrintableString ( mod_config_from_lib [ 0 ] , bpstrlen ( mod_config_from_lib [ 0 ] ) , BP_TRUE , BP_TRUE ) ) { P_BP_JSON mod_json = BP_JSONCreate ( ) ; if ( BP_JSONParseFromBuffer ( mod_json , mod_config_from_lib [ 0 ] , bpstrlen ( mod_config_from_lib [ 0 ] ) , 100 , 100 ) ) { BP_JSONDisplay ( mod_json ) ; BP_JSONFinalizeOutput ( mod_json ) ; BP_JSONDisplay ( mod_json ) ; tmp_module . so_module_name = current_module_iter -> key ; tmp_module . so_handle = so_handle ; tmp_module . so_module_config_json = mod_config_from_lib [ 0 ] ; tmp_module . so_module_load_path = ( char * ) so_path -> data ; tmp_module . so_module_filesystem_sha1_hash = ( char * ) & so_sha1 ; if ( ! BP_DynamicModuleLoadIntoGHT ( ( P_BP_DYNAMIC_MODULE ) & tmp_module ) ) printf ( " \n " , tmp_module . so_module_name ) ; } else { printf ( " \n " , tmp_module . so_module_name ) ; } if ( mod_json ) BP_JSONDestroy ( mod_json ) ; } } } } } BP_HASH_TABLE_LEAVE_CRITICAL_SECTION ( NULL ) ; P_BP_HTKE extra_data_table = BP_HashRegLookupTableEntryByDataKeyIndexAndTablePathQuery ( module_config -> json_out_hreg , current_module_table_path , " " ) ; if ( current_module_table_path ) bpfree ( current_module_table_path ) ; if ( ! tmp_module . loaded_ok ) { printf ( " \n " , tmp_module . so_module_name ) ; return ERR_FAILURE ; } } BP_HASH_ITER_CLOSE ; return ERR_SUCCESS ; }
All application wide dynamic loads are stored in the GHT only.
All application wide dynamic loads are stored in the GHT only .
// basic null checks // display the global hash table registry // Temporary module used during iteration.  It is filled out with REFERENCE DATA ONLY // and passed off to BP_DynamicModuleLoadIntoGHT().  Do not attempt to free it. // iterate through the modules // zero out the temporary module before loop // if the type is not a table, continue the loop // key must be reasonable/printable with no newlines/carriage returns // set parent table key (should always be top level table) // set module path // declare current module table path (must be freed) // lookup static entries // --- Null checks on mandatory data lookups // --- Data type checks // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% Process Data and Load Module %%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // attempt to enter critical section // create some temporary space on the stack to store our so sha1 value // attempt to sha1 the contents // printf("\n Module SHA1?: %s", so_sha1); // check that we've been able to create our sha1 hash ok // attempt to open the library // attempt to retrieve the module configuration // ensure we have a reference pointer // ensure reference is reasonable printable // create new json parser // after all cascading if() checks are passed, perform tmp_module data assignments // so that the module can be added to the ght dynamic_modules table. // attempt to load the dynamic module via parsed json // destroy the json session if it's set // attempt to leave critical section // --- Extra data // This is extra data which must be parsed down into json and provided to the module // when it's entry point is called. // destroy table path // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% Process Module Load Failures %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // if the mod hasn't loaded ok, exit indicating failure // return indicating success