freecwmp
[Top] [All Lists]

[PATCH v2 02/10] get_parameter_values method support many parameter nam

To: freecwmp@linux-mips.org
Subject: [PATCH v2 02/10] get_parameter_values method support many parameter names
From: Mohamed Kallel <mohamed.kallel@pivasoftware.com>
Date: Fri, 28 Dec 2012 16:59:39 +0100
Cc: freecwmp@lukaperkov.net, jogo@openwrt.org, Mohamed <mohamed.kallel@pivasoftware.com>, Ahmed Zribi <ahmed.zribi@pivasoftware.com>
In-reply-to: <1356710387-3043-1-git-send-email-mohamed.kallel@pivasoftware.com>
Original-recipient: rfc822;freecwmp@linux-mips.org
References: <1356710387-3043-1-git-send-email-mohamed.kallel@pivasoftware.com>
Sender: freecwmp-bounce@linux-mips.org
From: Mohamed <mohamed.kallel@pivasoftware.com>

The xml get_parameter_values handler is ready to get the value from external 
ubus output now. and  is supporting many parameters
Contributed by Inteno Broadband Technology AB && PIVA SOFTWARE

Signed-off-by: Mohamed Kallel <mohamed.kallel@pivasoftware.com>
Signed-off-by: Ahmed Zribi <ahmed.zribi@pivasoftware.com>
---
 bin/Makefile.am |    3 +-
 configure.ac    |    3 ++
 src/external.c  |   94 +++++++++++++++++++++++++++++++++++++++++++++++++++---
 src/external.h  |    5 ++-
 src/freecwmp.c  |   17 ++++++++++
 src/xml.c       |   81 +++++++++++++++++++++++++++++------------------
 6 files changed, 164 insertions(+), 39 deletions(-)

diff --git a/bin/Makefile.am b/bin/Makefile.am
index 75b9bda..9078ab3 100644
--- a/bin/Makefile.am
+++ b/bin/Makefile.am
@@ -48,5 +48,6 @@ freecwmpd_LDADD =             \
        $(LIBUBUS_LIBS)         \
        $(MICROXML_LIBS)        \
        $(LIBCURL_LIBS)         \
-       $(LIBZSTREAM_LIBS)
+       $(LIBZSTREAM_LIBS)      \
+       $(LIBPTHREAD_LIBS)
 
diff --git a/configure.ac b/configure.ac
index 5ae95c4..765bfe0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -28,6 +28,9 @@ AC_PROG_CC
 AM_PROG_CC_C_O
 
 # checks for libraries
+LIBPTHREAD_LIBS='-lpthread'
+AC_SUBST([LIBPTHREAD_LIBS])
+
 AC_ARG_WITH([libfreecwmp-include-path],
   [AS_HELP_STRING([--with-libfreecwmp-include-path],
     [location of the libfreecwmp library headers])],
diff --git a/src/external.c b/src/external.c
index 46a4931..44be0b6 100644
--- a/src/external.c
+++ b/src/external.c
@@ -5,6 +5,7 @@
  *     (at your option) any later version.
  *
  *     Copyright (C) 2011 Luka Perkov <freecwmp@lukaperkov.net>
+ *     Copyright (C) 2012 Mohamed Kallel <mohamed.kallel@pivasoftware.com>
  */
 
 #include <errno.h>
@@ -25,8 +26,15 @@
 #include "freecwmp.h"
 
 static struct uloop_process uproc;
+pthread_t ubus_thread;
 LIST_HEAD(external_list_parameter);
 
+void *thread_uloop_run(void *v)
+{
+       uloop_run();
+       return NULL;
+}
+
 void external_add_list_paramameter(char *param_name, char *param_data, char 
*param_type, char *fault_code)
 {
        struct external_parameter *external_parameter;
@@ -140,6 +148,80 @@ error:
        return -1;
 }
 
+int external_get_action_write(char *action, char *name, char *arg)
+{
+       lfc_log_message(NAME, L_NOTICE, "adding to get %s script '%s'\n",
+                       action, name);
+
+       FILE *fp;
+
+       if (access(fc_script_actions, R_OK | W_OK | X_OK) != -1) {
+               fp = fopen(fc_script_actions, "a");
+               if (!fp) return -1;
+       } else {
+               fp = fopen(fc_script_actions, "w");
+               if (!fp) return -1;
+
+               fprintf(fp, "#!/bin/sh\n");
+
+               if (chmod(fc_script_actions,
+                       strtol("0700", 0, 8)) < 0) {
+                       return -1;
+               }
+       }
+
+#ifdef DUMMY_MODE
+       fprintf(fp, "/bin/sh `pwd`/%s --ubus get %s %s %s\n", fc_script, 
action, name, arg ? arg : "");
+#else
+       fprintf(fp, "/bin/sh %s --ubus get %s %s %s\n", fc_script, action, 
name, arg ? arg : "");
+#endif
+
+       fclose(fp);
+
+       return 0;
+}
+
+int external_get_action_execute()
+{
+       lfc_log_message(NAME, L_NOTICE, "executing get script\n");
+
+       pthread_create(&ubus_thread, NULL, &thread_uloop_run, NULL);
+
+       if ((uproc.pid = fork()) == -1) {
+               return -1;
+       }
+
+       if (uproc.pid == 0) {
+               /* child */
+
+               const char *argv[3];
+               int i = 0;
+               argv[i++] = "/bin/sh";
+               argv[i++] = fc_script_actions;
+               argv[i++] = NULL;
+
+               execvp(argv[0], (char **) argv);
+               exit(ESRCH);
+
+       } else if (uproc.pid < 0)
+       return -1;
+
+       /* parent */
+       int status;
+       while (wait(&status) != uproc.pid) {
+               DD("waiting for child to exit");
+       }
+
+       pthread_cancel(ubus_thread);
+       pthread_join(ubus_thread, NULL);
+
+       // TODO: add some kind of checks
+
+       remove(fc_script_actions);
+
+       return 0;
+}
+
 int external_set_action_write(char *action, char *name, char *value)
 {
        lfc_log_message(NAME, L_NOTICE, "adding to set %s script '%s'\n",
@@ -147,16 +229,16 @@ int external_set_action_write(char *action, char *name, 
char *value)
 
        FILE *fp;
 
-       if (access(fc_script_set_actions, R_OK | W_OK | X_OK) != -1) {
-               fp = fopen(fc_script_set_actions, "a");
+       if (access(fc_script_actions, R_OK | W_OK | X_OK) != -1) {
+               fp = fopen(fc_script_actions, "a");
                if (!fp) return -1;
        } else {
-               fp = fopen(fc_script_set_actions, "w");
+               fp = fopen(fc_script_actions, "w");
                if (!fp) return -1;
 
                fprintf(fp, "#!/bin/sh\n");
 
-               if (chmod(fc_script_set_actions,
+               if (chmod(fc_script_actions,
                        strtol("0700", 0, 8)) < 0) {
                        return -1;
                }
@@ -187,7 +269,7 @@ int external_set_action_execute()
                const char *argv[3];
                int i = 0;
                argv[i++] = "/bin/sh";
-               argv[i++] = fc_script_set_actions;
+               argv[i++] = fc_script_actions;
                argv[i++] = NULL;
 
                execvp(argv[0], (char **) argv);
@@ -204,7 +286,7 @@ int external_set_action_execute()
 
        // TODO: add some kind of checks
 
-       if (remove(fc_script_set_actions) != 0)
+       if (remove(fc_script_actions) != 0)
                return -1;
 
        return 0;
diff --git a/src/external.h b/src/external.h
index 0e09415..f69fb34 100644
--- a/src/external.h
+++ b/src/external.h
@@ -5,6 +5,7 @@
  *     (at your option) any later version.
  *
  *     Copyright (C) 2011 Luka Perkov <freecwmp@lukaperkov.net>
+ *     Copyright (C) 2012 Mohamed Kallel <mohamed.kallel@pivasoftware.com>
  */
 
 #ifndef _FREECWMP_EXTERNAL_H__
@@ -16,7 +17,7 @@ static char *fc_script = "./ext/openwrt/scripts/freecwmp.sh";
 #else
 static char *fc_script = "/usr/sbin/freecwmp";
 #endif
-static char *fc_script_set_actions = "/tmp/freecwmp_set_action_values.sh";
+static char *fc_script_actions = "/tmp/freecwmp_actions.sh";
 
 /*
  * external_parameter structure is used to get data from external command when 
a parameter method is triggered
@@ -31,6 +32,8 @@ struct external_parameter {
 };
 
 int external_get_action(char *action, char *name, char **value);
+int external_get_action_write(char *action, char *name, char *arg);
+int external_get_action_execute();
 int external_set_action_write(char *action, char *name, char *value);
 int external_set_action_execute();
 int external_simple(char *arg);
diff --git a/src/freecwmp.c b/src/freecwmp.c
index d311cf4..0ad0e94 100644
--- a/src/freecwmp.c
+++ b/src/freecwmp.c
@@ -18,6 +18,7 @@
 #include <arpa/inet.h>
 #include <linux/netlink.h>
 #include <linux/rtnetlink.h>
+#include <signal.h>
 
 #include <libfreecwmp.h>
 #include <libubox/uloop.h>
@@ -194,11 +195,27 @@ netlink_init(void)
        return 0;
 }
 
+void signal_kill_all_handler(int sig)
+{
+       pthread_exit(NULL);
+}
+
 int main (int argc, char **argv)
 {
        lfc_log_message(NAME, L_NOTICE, "daemon started\n");
 
        bool foreground = false;
+       struct sigaction sigint_action;
+
+       sigint_action.sa_handler = &signal_kill_all_handler;
+       sigemptyset(&sigint_action.sa_mask);
+
+       /*
+        * reset handler in case when pthread_cancel didn't stop
+        * threads for some reason
+        */
+       sigint_action.sa_flags = SA_RESETHAND;
+       sigaction(SIGTERM, &sigint_action, NULL);
 
        setlocale(LC_CTYPE, "");
        umask(0037);
diff --git a/src/xml.c b/src/xml.c
index 0aa4f35..f89fd3c 100644
--- a/src/xml.c
+++ b/src/xml.c
@@ -21,6 +21,8 @@
 #include "messages.h"
 #include "time.h"
 
+extern struct list_head external_list_parameter;
+
 struct rpc_method {
        const char *name;
        int (*handler)(mxml_node_t *body_in, mxml_node_t *tree_in,
@@ -628,7 +630,8 @@ int xml_handle_get_parameter_values(mxml_node_t *body_in,
                                    mxml_node_t *tree_in,
                                    mxml_node_t *tree_out)
 {
-       mxml_node_t *n, *b = body_in;
+       mxml_node_t *n, *parameter_list, *b = body_in;
+       struct external_parameter *external_parameter;
        char *parameter_name = NULL;
        char *parameter_value = NULL;
        char *c;
@@ -656,54 +659,71 @@ int xml_handle_get_parameter_values(mxml_node_t *body_in,
                        parameter_name = b->value.text.string;
                }
 
+               /*
+                * If the string node from GetParameterValues does not contain 
child node (txt node)
+                * Then the parameter name is empty string which means get all 
parameters from the data model
+                */
+               if (b && b->type == MXML_ELEMENT &&
+                       !strcmp(b->value.element.name, "string") &&
+                       !b->child) {
+                       parameter_name = "";
+               }
+
                if (parameter_name) {
                        if (!config_get_cwmp(parameter_name, &parameter_value)) 
{
+                               
external_add_list_paramameter(parameter_name,parameter_value, "xsd:string", 
NULL);
+                               FREE(parameter_value);
                                // got the parameter value using libuci
-                       } else if (!external_get_action("value",
-                                       parameter_name, &parameter_value)) {
+                       } else if (!external_get_action_write("value", 
parameter_name, NULL)) {
                                // got the parameter value via external script
                        } else {
                                // error occurred when getting parameter value
                                goto out;
                        }
-                       counter++;
+               }
 
-                       n = mxmlFindElement(tree_out, tree_out, 
"ParameterList", NULL, NULL, MXML_DESCEND);
-                       if (!n) goto out;
+               b = mxmlWalkNext(b, body_in, MXML_DESCEND);
+               parameter_name = NULL;
+       }
 
-                       n = mxmlNewElement(n, "ParameterValueStruct");
-                       if (!n) goto out;
+       if (external_get_action_execute())
+               goto out;
 
-                       n = mxmlNewElement(n, "Name");
-                       if (!n) goto out;
+       parameter_list = mxmlFindElement(tree_out, tree_out, "ParameterList", 
NULL, NULL, MXML_DESCEND);
+       if (!parameter_list) goto out;
 
-                       n = mxmlNewText(n, 0, parameter_name);
-                       if (!n) goto out;
+       while (external_list_parameter.next != &external_list_parameter) {
+
+               external_parameter = list_entry(external_list_parameter.next, 
struct external_parameter, list);
+
+               if (external_parameter->fault_code && 
external_parameter->fault_code[0]=='9') {
+                       // TODO return FAULT message the fault code is saved in 
external_parameter->fault_code
+                       goto out;
+               }
 
-                       n = n->parent->parent;
-                       n = mxmlNewElement(n, "Value");
+               n = mxmlNewElement(parameter_list, "ParameterValueStruct");
                        if (!n) goto out;
 
+               n = mxmlNewElement(n, "Name");
+               if (!n) goto out;
+
+               n = mxmlNewText(n, 0, external_parameter->name);
+               if (!n) goto out;
+
+               n = n->parent->parent;
+               n = mxmlNewElement(n, "Value");
+               if (!n) goto out;
+
 #ifdef ACS_MULTI
-                       mxmlElementSetAttr(n, "xsi:type", "xsd:string");
+               mxmlElementSetAttr(n, "xsi:type", external_parameter->type);
 #endif
-                       n = mxmlNewText(n, 0, parameter_value ? parameter_value 
: "");
-                       if (!n) goto out;
+               n = mxmlNewText(n, 0, external_parameter->data ? 
external_parameter->data : "");
+               if (!n) goto out;
 
-                       /*
-                        * three day's work to finally find memory leak if we
-                        * free parameter_name;
-                        * it points to: b->value.text.string
-                        *
-                        * also, parameter_value can be NULL so we don't do 
checks
-                        */
-                       parameter_name = NULL;
-               }
+               counter++;
                
-               FREE(parameter_value);
-               b = mxmlWalkNext(b, body_in, MXML_DESCEND);
+               external_parameter_delete(external_parameter);
        }
-
 #ifdef ACS_MULTI
        b = mxmlFindElement(tree_out, tree_out, "ParameterList", 
                            NULL, NULL, MXML_DESCEND);
@@ -716,11 +736,10 @@ int xml_handle_get_parameter_values(mxml_node_t *body_in,
        FREE(c);
 #endif
 
-       FREE(parameter_value);
        return 0;
 
 out:
-       FREE(parameter_value);
+       external_free_list_parameter();
        return -1;
 }
 
-- 
1.7.4.1


<Prev in Thread] Current Thread [Next in Thread>