Committer: Tim Just <tim.just@xxxxxxxxxxxxxx> Date: Fri Jan 29 15:17:30 2010 +0100 Revision: 3509 Revision-id: tim.just@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Branch nick: tiny Log: Applied modularization concept on tiny branch. Added the python script process_modules.py for mdule configuration. Created example module 'update' with original update code. Modified: A modules/ A modules/update/ A modules/update/Makefile.am A modules/update/hipd/ A modules/update/module_info.xml A process_modules.py A project_info.xml R hipd/update.c => modules/update/hipd/update.c R hipd/update.c.doxyme => modules/update/hipd/update.c.doxyme R hipd/update.h => modules/update/hipd/update.h R hipd/update.h.doxyme => modules/update/hipd/update.h.doxyme R hipd/update_legacy.c => modules/update/hipd/update_legacy.c R hipd/update_legacy.c.doxyme => modules/update/hipd/update_legacy.c.doxyme R hipd/update_legacy.h => modules/update/hipd/update_legacy.h R hipd/update_legacy.h.doxyme => modules/update/hipd/update_legacy.h.doxyme M Makefile.am M autogen.sh M configure.ac M hipd/hadb.h M hipd/init.c M hipd/maintenance.c M hipd/maintenance.h M hipd/user.c M modules/update/hipd/update.c M modules/update/hipd/update.h === modified file 'Makefile.am' --- Makefile.am 2010-01-25 17:00:29 +0000 +++ Makefile.am 2010-01-29 14:17:30 +0000 @@ -116,8 +116,7 @@ tools_pisacert_SOURCES = tools/pisacert.c -hipd_hipd_SOURCES = hipd/update.c \ - hipd/hipd.c \ +hipd_hipd_SOURCES = hipd/hipd.c \ hipd/keymat.c \ hipd/hiprelay.c \ hipd/registration.c \ @@ -147,7 +146,6 @@ hipd/esp_prot_light_update.c \ hipd/nsupdate.c \ hipd/hit_to_ip.c \ - hipd/update_legacy.c \ hipd/hadb_legacy.c \ hipd/heartbeat.c @@ -322,6 +320,8 @@ endif # HIP_FIREWALL +include Makefile.modules + CLEANFILES = tools/hipdnsproxy tools/hipdnskeyparse ###### PYTHON stuff below ###### === modified file 'autogen.sh' --- autogen.sh 2010-01-03 15:54:35 +0000 +++ autogen.sh 2010-01-29 14:17:30 +0000 @@ -77,6 +77,9 @@ exit fi +# Create empty file needed by automake. +touch Makefile.modules + display_pre_info setup_hipl && display_post_info === modified file 'configure.ac' --- configure.ac 2010-01-25 16:48:47 +0000 +++ configure.ac 2010-01-29 14:17:30 +0000 @@ -312,4 +312,14 @@ # Set default AM_CFLAGS for the complete project. AC_SUBST(AM_CFLAGS, "-Werror -Wredundant-decls -Wall -Wcast-align -Wdisabled-optimization -Wundef -Wstrict-prototypes -Wno-deprecated-declarations -fno-strict-aliasing $OPENWRT_CFLAGS $GPROF_CFLAGS -D_GNU_SOURCE") +# Parse modules directory +echo "" +echo "+-----------------------------------------------"; +echo "| processing modules..."; +echo "|"; +python process_modules.py $DISABLE_MODULES +echo "|"; +echo "+-----------------------------------------------" +echo "" + AC_OUTPUT === modified file 'hipd/hadb.h' --- hipd/hadb.h 2010-01-22 12:30:54 +0000 +++ hipd/hadb.h 2010-01-29 14:17:30 +0000 @@ -14,12 +14,14 @@ #include "lib/core/state.h" #include "lib/core/builder.h" #include "input.h" // required for declaration of receive functions -#include "update.h" // required for declaration of update function #include "user_ipsec_sadb_api.h" #include "lib/tool/xfrmapi.h" #include "nat.h" #include "hadb_legacy.h" +/* TODO Remove this include, when modularization is finished */ +#include "modules/update/hipd/update.h" // required for declaration of update function + #define HIP_LOCK_INIT(ha) #define HIP_LOCK_HA(ha) #define HIP_UNLOCK_HA(ha) === modified file 'hipd/init.c' --- hipd/init.c 2010-01-21 16:49:45 +0000 +++ hipd/init.c 2010-01-29 14:17:30 +0000 @@ -14,6 +14,9 @@ #include "config.h" #endif /* HAVE_CONFIG_H */ +/* Required for modularization */ +#include "modules/hipd_modules.h" + #include "lib/core/common_defines.h" #include "lib/core/debug.h" #include "lib/core/hip_capability.h" @@ -398,7 +401,7 @@ */ int hipd_init(int flush_ipsec, int killold) { - int err = 0, certerr = 0, hitdberr = 0; + int err = 0, certerr = 0, hitdberr = 0, i; unsigned int mtu_val = HIP_HIT_DEV_MTU; char str[64]; char mtu[16]; @@ -601,6 +604,11 @@ if (hip_get_nsupdate_status()) nsupdate(1); + /* Initialize modules */ + for (i = 0; i < num_modules_hipd; i++) { + hipd_init_functions[i](); + } + out_err: return err; } === modified file 'hipd/maintenance.c' --- hipd/maintenance.c 2010-01-22 10:35:37 +0000 +++ hipd/maintenance.c 2010-01-29 14:17:30 +0000 @@ -15,9 +15,11 @@ #endif /* HAVE_CONFIG_H */ #include "maintenance.h" -#include "update.h" #include "heartbeat.h" -#include "hipd.h" + +/* TODO Remove these includes, when modularization is finished */ +#include "modules/update/hipd/update.h" +#include "modules/update/hipd/update_legacy.h" #define FORCE_EXIT_COUNTER_START 5 === modified file 'hipd/maintenance.h' --- hipd/maintenance.h 2010-01-22 10:35:37 +0000 +++ hipd/maintenance.h 2010-01-29 14:17:30 +0000 @@ -8,8 +8,6 @@ #include "oppdb.h" #include "lib/core/hip_statistics.h" #include "nat.h" -#include "update.h" -#include "update_legacy.h" extern int heartbeat_counter; === modified file 'hipd/user.c' --- hipd/user.c 2010-01-22 14:29:13 +0000 +++ hipd/user.c 2010-01-29 14:17:30 +0000 @@ -20,6 +20,9 @@ #include "esp_prot_anchordb.h" #include "hipd.h" +/* TODO Remove these includes, when modularization is finished */ +#include "modules/update/hipd/update_legacy.h" + int hip_sendto_user(const struct hip_common *msg, const struct sockaddr *dst){ HIP_DEBUG("Sending msg type %d\n", hip_get_msg_type(msg)); return sendto(hip_user_sock, msg, hip_get_msg_total_len(msg), === added directory 'modules' === added directory 'modules/update' === added file 'modules/update/Makefile.am' --- modules/update/Makefile.am 1970-01-01 00:00:00 +0000 +++ modules/update/Makefile.am 2010-01-29 14:17:30 +0000 @@ -0,0 +1,3 @@ +lib_LTLIBRARIES += modules/update/hipd/libhipupdate.la +modules_update_hipd_libhipupdate_la_SOURCES = modules/update/hipd/update.c \ + modules/update/hipd/update_legacy.c \ No newline at end of file === added directory 'modules/update/hipd' === renamed file 'hipd/update.c' => 'modules/update/hipd/update.c' --- hipd/update.c 2010-01-19 13:06:23 +0000 +++ modules/update/hipd/update.c 2010-01-29 14:17:30 +0000 @@ -16,9 +16,9 @@ #include "update.h" +#include "lib/core/builder.h" #include "lib/core/protodefs.h" -#include "netdev.h" -#include "lib/core/builder.h" +#include "hipd/netdev.h" #include "update_legacy.h" #ifdef CONFIG_HIP_PERFORMANCE @@ -26,11 +26,17 @@ #endif #ifdef CONFIG_HIP_MIDAUTH -#include "pisa.h" +#include "hipd/pisa.h" #endif int update_id_window_size = 50; +int update_init(void) +{ + HIP_DEBUG("update_init called!\n"); + return 0; +} + int hip_create_locators(hip_common_t* locator_msg, struct hip_locator_info_addr_item **locators) { === renamed file 'hipd/update.c.doxyme' => 'modules/update/hipd/update.c.doxyme' === renamed file 'hipd/update.h' => 'modules/update/hipd/update.h' --- hipd/update.h 2010-01-19 09:28:42 +0000 +++ modules/update/hipd/update.h 2010-01-29 14:17:30 +0000 @@ -10,7 +10,9 @@ #define HIP_UPDATE_H #include "lib/core/builder.h" -#include "hadb.h" +#include "hipd/hadb.h" + +int update_init(void); /** * Sends all the locators from our active source address to the active === renamed file 'hipd/update.h.doxyme' => 'modules/update/hipd/update.h.doxyme' === renamed file 'hipd/update_legacy.c' => 'modules/update/hipd/update_legacy.c' === renamed file 'hipd/update_legacy.c.doxyme' => 'modules/update/hipd/update_legacy.c.doxyme' === renamed file 'hipd/update_legacy.h' => 'modules/update/hipd/update_legacy.h' === renamed file 'hipd/update_legacy.h.doxyme' => 'modules/update/hipd/update_legacy.h.doxyme' === added file 'modules/update/module_info.xml' --- modules/update/module_info.xml 1970-01-01 00:00:00 +0000 +++ modules/update/module_info.xml 2010-01-29 14:17:30 +0000 @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- Mandatory: name, version --> +<module + name="update" + version="0.0.1" + description="Update functionality for the hip daemon." + developer="" + bugaddress="hipl-users@xxxxxxxxxxxxx" + webpage="http://infrahip.hiit.fi/";> + + <!-- Mandatory: name, header_file, init_function, linkcommand --> + <application + name="hipd" + header_file="modules/update/hipd/update.h" + init_function="update_init" + linkcommand="hipd_hipd_LDADD += modules/update/hipd/libhipupdate.la" /> +</module> \ No newline at end of file === added file 'process_modules.py' --- process_modules.py 1970-01-01 00:00:00 +0000 +++ process_modules.py 2010-01-29 14:17:30 +0000 @@ -0,0 +1,303 @@ +#!/usr/bin/python +import glob, os, sys, xml.dom.minidom + + +### Constants ### +INFO_FILE_PATH = 'project_info.xml' + +APPLICATION_TAG_NAME = 'application' +APPLICATION_ATTR_NAME = 'name' +APPLICATION_PATH_NAME = 'path' + +MODULES_DIR = 'modules' +MODULE_INFO_FILE = 'module_info.xml' + +HEADER_FILE_DIR = MODULES_DIR +HEADER_FILE_SUFFIX = '_modules.h' + + +### Functions ### + +# Parses the XML document at 'path' and returns a list of application names +def parse_info_file(path): + + file = open(path, "r") + dom = xml.dom.minidom.parse(file) + file.close() + + apps = {} + + for current_app in dom.getElementsByTagName(APPLICATION_TAG_NAME): + name = str(current_app.attributes[APPLICATION_ATTR_NAME].value) + path = str(current_app.attributes[APPLICATION_PATH_NAME].value) + apps[name] = path + + compile_type = 'all' + if 0 < len(dom.getElementsByTagName('compile_type')): + node = dom.getElementsByTagName('compile_type')[0]; + compile_type = node.childNodes[0].nodeValue + + # Read list of disabled modules from command line and convert to set + disabled_modules = sys.argv + disabled_modules.pop(0) + disabled_modules = set(disabled_modules) + + # Read list of disabled modules from configuration file and add to set (unique) + if 0 < len(dom.getElementsByTagName('disabled_modules')): + for node in dom.getElementsByTagName('disabled_modules')[0].getElementsByTagName('module'): + disabled_modules.add(str(node.attributes['name'].value)) + + return (apps, compile_type, disabled_modules) + +# Parses the XML document at 'path' and returns a dictionary with module info +def parse_module_info(path, applications): + + file = open(path, "r") + dom = xml.dom.minidom.parse(file) + file.close() + + module_info = {} + + module_name = str(dom.getElementsByTagName('module')[0].attributes['name'].value) + module_info['version'] = str(dom.getElementsByTagName('module')[0].attributes['version'].value) + + module_info['requires'] = [] + if 0 < len(dom.getElementsByTagName('requires')): + for node in dom.getElementsByTagName('requires')[0].getElementsByTagName('module'): + current_req = {} + current_req['name'] = str(node.attributes['name'].value) + if 'minversion' in node.attributes.keys(): + current_req['minversion'] = str(node.attributes['minversion'].value) + if 'maxversion' in node.attributes.keys(): + current_req['maxversion'] = str(node.attributes['maxversion'].value) + + module_info['requires'].append(current_req) + + module_info['conflicts'] = [] + if 0 < len(dom.getElementsByTagName('conflicts')): + for node in dom.getElementsByTagName('conflicts')[0].getElementsByTagName('module'): + current_con = {} + current_con['name'] = str(node.attributes['name'].value) + if 'minversion' in node.attributes.keys(): + current_con['minversion'] = str(node.attributes['minversion'].value) + if 'maxversion' in node.attributes.keys(): + current_con['maxversion'] = str(node.attributes['maxversion'].value) + + module_info['conflicts'].append(current_con) + + module_info['application'] = {} + if 0 == len(dom.getElementsByTagName('application')): + print '|\n| WARNING in configuration of ' + module_name + ':', + print 'no application tag found' + print '| Please check configuration file' + raise Error() + + for current_app in dom.getElementsByTagName('application'): + app_info = {} + name = str(current_app.attributes['name'].value) + if False == (name in applications.keys()): + print '|\n| WARNING in configuration of ' + module_name + ':', + print 'unknown application ' + name + print '| Please check configuration file' + raise Error() + + app_info['header_file'] = str(current_app.attributes['header_file'].value) + app_info['init_function'] = str(current_app.attributes['init_function'].value) + app_info['linkcommand'] = str(current_app.attributes['linkcommand'].value) + module_info['application'][name] = app_info + + return (module_name, module_info) + +# Tries to read the XML configuration files for all sub-folders in the given +# directory and returns a dictionary containing the module information +def read_module_info(MODULES_DIR, disabled_modules, applications, compile_type): + + # Initialize output variable + module_info = {} + + # Iterate through all sub directories in MODULES_DIR + for current_module in glob.glob(MODULES_DIR + '/*/'): + cont = False + # Check if current_module is disabled + for disabled in disabled_modules: + if current_module == os.path.join(MODULES_DIR, disabled) + '/': + cont = True + print '| ' + disabled + ' is disabled' + if 'all' == compile_type: + print '| ...this module will be compiled, but not linked!\n|' + elif 'enabled' == compile_type: + print '| ...this module will not be compiled!\n|' + else: + print '| ...ignoring this directory!\n|' + if True == cont: + continue + + try: + path = os.path.join(current_module, MODULE_INFO_FILE) + (name, info) = parse_module_info(path, applications) + print '| found module: ' + name, + print '(version ' + info['version'] + ')' + module_info[name] = info + except: + print '|\n| WARNING parsing of module info file', + print '\'' + path + '\' failed!' + print '| ...ignoring this directory\n|' + + return module_info + +# Checks the module_info data structure for missing dependencies and conflicts +# between modules. Returns a +def process_module_info(module_info): + + includes = {} + init_functions = {} + num_modules = {} + + for current_module in module_info.keys(): + # Check for dependencies + for require in module_info[current_module]['requires']: + if False == (require['name'] in module_info.keys()): + print '|\n| ERROR ' + current_module, + print 'requires module ' + require['name'] + sys.exit('| ...abort current run. Please check module configuration\n|') + else: + req_version = module_info[require['name']]['version'] + + if require.has_key('minversion') and req_version < require['minversion']: + print '|\n| ERROR ' + current_module + ' requires module', + print require['name'] + ' at least in version ' + require['minversion'] + sys.exit('| ...abort current run. Please check module configuration\n|') + if require.has_key('maxversion') and req_version > require['maxversion']: + print '|\n| ERROR ' + current_module + ' requires module', + print require['name'] + ' at most in version ' + require['maxversion'] + sys.exit('| ...abort current run. Please check module configuration\n|') + + # Check for conflicts + for conflict in module_info[current_module]['conflicts']: + if conflict['name'] in module_info.keys(): + con_version = module_info[conflict['name']]['version'] + + if False == ((conflict.has_key('minversion') and + con_version < conflict['minversion']) or + (conflict.has_key('maxversion') and + con_version > conflict['maxversion'])): + print '| ERROR ' + current_module + ' conflicts with module ' + conflict['name'] + ' (version ' + con_version + ')' + sys.exit('| ...abort current run. Please check module configuration\n|') + + for current_module in module_info.keys(): + for app_name in module_info[current_module]['application'].keys(): + # Build includes + if includes.has_key(app_name): + tmp = includes.pop(app_name) + else: + tmp = [] + + tmp.append(module_info[current_module]['application'][app_name]['header_file']) + includes[app_name] = tmp + + # Build init_functions + if init_functions.has_key(app_name): + tmp = init_functions.pop(app_name) + else: + tmp = [] + + tmp.append(module_info[current_module]['application'][app_name]['init_function']) + init_functions[app_name] = tmp + + return (includes, init_functions) + +# Creates a C header file with the given filename an the needed includes, +# the number of init functions per application and an array of function +# pointers for each application +def create_header_files(output_dir, suffix, applications, includes, init_functions): + + for current_app in applications.keys(): + + hdr_file_path = os.path.join(output_dir, current_app + suffix) + hdr_file = open(hdr_file_path, 'w') + + app_string = 'HIP_' + current_app.upper() + '_MODULES_H' + + hdr_file.write('#ifndef ' + app_string + '\n') + hdr_file.write('#define ' + app_string + '\n') + + if includes.has_key(current_app) and init_functions.has_key(current_app): + + num_modules = str(len(init_functions[current_app])); + for current in includes[current_app]: + hdr_file.write('\n#include \"' + current + '\"') + + hdr_file.write('\n\ntypedef int (*pt2Function)(void);\n') + hdr_file.write('\nconst int num_modules_' + current_app + ' = ') + hdr_file.write(num_modules + ';') + + hdr_file.write('\n\nstatic const pt2Function ' + current_app) + hdr_file.write('_init_functions[' + num_modules + '] = {') + + first_loop = True + for function in init_functions[current_app]: + if first_loop != True: + hdr_file.write(', ') + hdr_file.write('&' + function) + first_loop = False + hdr_file.write('};') + else: + hdr_file.write('\n\ntypedef int (*pt2Function)(void);\n') + hdr_file.write('\nconst int num_modules_' + current_app + ' = 0;') + + hdr_file.write('\n\nstatic const pt2Function ' + current_app) + hdr_file.write('_init_functions[0] = {}') + + hdr_file.write('\n\n#endif /* ' + app_string + ' */') + hdr_file.close() + + print '| created file: ' + hdr_file_path + +# Creates a file at file_path and includes a Makefile.am from all given modules +# sub directories. +def create_makefile_modules(file_path, + module_info, + disabled_modules, + applications, + compile_type): + + makefile_modules = open(file_path, 'w') + + enabled_modules = module_info.keys() + all_modules = enabled_modules + list(disabled_modules) + + if 'all' == compile_type: + compile_modules = all_modules + elif 'enabled' == compile_type: + compile_modules = enabled_modules + else: + print '|\n| ERROR compile_type \'' + compile_type + '\' is unknown.' + sys.exit('| ...abort current run. Please check project configuration\n|') + + # Include compile statements from module Makefile.am's + for current in compile_modules: + path = os.path.join(MODULES_DIR, current, 'Makefile.am') + makefile_modules.write('include ' + path + '\n') + + makefile_modules.write('\n') + # Write linker commands to Makefile.modules + for current_module in enabled_modules: + for current_app in module_info[current_module]['application']: + linkcommand = module_info[current_module]['application'][current_app]['linkcommand'] + makefile_modules.write(linkcommand + '\n') + + makefile_modules.close() + print '| created file: ' + file_path + + +### Main program ### + +(applications, compile_type, disabled_modules) = parse_info_file(INFO_FILE_PATH) + +module_info = read_module_info(MODULES_DIR, disabled_modules, applications, compile_type) + +(includes, init_functions) = process_module_info(module_info) + +create_header_files(HEADER_FILE_DIR, HEADER_FILE_SUFFIX, applications, includes, init_functions) + +create_makefile_modules('Makefile.modules', module_info, disabled_modules, applications, compile_type) === added file 'project_info.xml' --- project_info.xml 1970-01-01 00:00:00 +0000 +++ project_info.xml 2010-01-29 14:17:30 +0000 @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<hipl> + <application name="hipd" path="hidp/hipd" /> + <application name="hipfw" path="firewall/hipfw" /> + + <!-- compile all code or only enabled modules (values: all/enabled) --> + <compile_type>all</compile_type> + + <!-- + <disabled_modules> + <module name="update" /> + </disabled_modules> + --> +</hipl>