[hipl-commit] [tiny] Rev 3509: Applied modularization concept on tiny branch.

  • From: Tim Just <tim.just@xxxxxxxxxxxxxx>
  • To: hipl-commit@xxxxxxxxxxxxx
  • Date: Fri, 29 Jan 2010 16:20:03 +0200

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>

Other related posts: