freecwmp
[Top] [All Lists]

[PATCH v2 06/10] Add xml_get_parameter_name handler.

To: freecwmp@linux-mips.org
Subject: [PATCH v2 06/10] Add xml_get_parameter_name handler.
From: Mohamed Kallel <mohamed.kallel@pivasoftware.com>
Date: Fri, 28 Dec 2012 16:59:43 +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>

Add in the core (only C) the get_parameter_name handler, and add also the ubus 
related function in order to get from scripts the parameter names
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>
---
 src/cwmp.c     |    2 +-
 src/external.c |   73 ++++++++++++++-----------------------
 src/external.h |    3 +-
 src/ubus.c     |   40 ++++++++++++++++++++
 src/xml.c      |  110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/xml.h      |    4 ++
 6 files changed, 185 insertions(+), 47 deletions(-)

diff --git a/src/cwmp.c b/src/cwmp.c
index f1f5e9f..18c8ff4 100644
--- a/src/cwmp.c
+++ b/src/cwmp.c
@@ -248,7 +248,7 @@ void cwmp_clear_events(void)
 void cwmp_add_notification(char *parameter, char *value, char *type)
 {
        char *c = NULL;
-       external_get_action("notification", parameter, &c);
+       external_get_action_data("notification", parameter, &c);
        if (!c) return;
 
        struct notification *n = NULL;
diff --git a/src/external.c b/src/external.c
index 44be0b6..80c8108 100644
--- a/src/external.c
+++ b/src/external.c
@@ -66,14 +66,34 @@ void external_free_list_parameter()
        }
 }
 
-int external_get_action(char *action, char *name, char **value)
+int external_get_action_data(char *action, char *name, char **value)
+{
+       struct external_parameter *external_parameter;
+       external_get_action(action, name, NULL);
+       if (external_list_parameter.next!=&external_list_parameter) {
+               external_parameter = list_entry(external_list_parameter.next, 
struct external_parameter, list);
+               if (external_parameter->data)
+                       *value = strdup(external_parameter->data);
+               external_parameter_delete(external_parameter);
+       }
+       external_free_list_parameter();
+       return 0;
+}
+
+/*
+ * external_get_action allow to execute external commands related to get 
methods:
+ * GetParameterNames, GetParameterValues, GetParameterAttributes
+ * Input:
+ * - action: external action to execute: get value, or get name, or get 
notification
+ * - name: the parameter name
+ * - arg: is used only in case of GetParameterNames to indicate the NextLevel 
argument
+ */
+int external_get_action(char *action, char *name, char *arg)
 {
        lfc_log_message(NAME, L_NOTICE, "executing get %s '%s'\n",
                        action, name);
 
-       int pfds[2];
-       if (pipe(pfds) < 0)
-               return -1;
+       pthread_create(&ubus_thread, NULL, &thread_uloop_run, NULL);
 
        if ((uproc.pid = fork()) == -1)
                goto error;
@@ -85,66 +105,29 @@ int external_get_action(char *action, char *name, char 
**value)
                int i = 0;
                argv[i++] = "/bin/sh";
                argv[i++] = fc_script;
-               argv[i++] = "--newline";
-               argv[i++] = "--value";
+               argv[i++] = "--ubus";
                argv[i++] = "get";
                argv[i++] = action;
                argv[i++] = name;
+               if (arg) argv[i++] = arg;
                argv[i++] = NULL;
 
-               close(pfds[0]);
-               dup2(pfds[1], 1);
-               close(pfds[1]);
-
                execvp(argv[0], (char **) argv);
                exit(ESRCH);
 
        } else if (uproc.pid < 0)
                goto error;
 
-       /* parent */
-       close(pfds[1]);
-
        int status;
        while (wait(&status) != uproc.pid) {
                DD("waiting for child to exit");
        }
+       pthread_cancel(ubus_thread);
+       pthread_join(ubus_thread, NULL);
 
-       char buffer[64];
-       ssize_t rxed;
-       char *c;
-       int t;
-
-       *value = NULL;
-       while ((rxed = read(pfds[0], buffer, sizeof(buffer))) > 0) {
-               if (*value)
-                       t = asprintf(&c, "%s%.*s", *value, (int) rxed, buffer);
-               else
-                       t = asprintf(&c, "%.*s", (int) rxed, buffer);
-
-               if (t == -1) goto error;
-
-               free(*value);
-               *value = strdup(c);
-               free(c);
-       }
-
-       if (!strlen(*value)) {
-               FREE(*value);
-               goto done;
-       }
-
-       if (rxed < 0)
-               goto error;
-
-done:
-       close(pfds[0]);
        return 0;
 
 error:
-       FREE(*c);
-       FREE(*value);
-       close(pfds[0]);
        return -1;
 }
 
diff --git a/src/external.h b/src/external.h
index f69fb34..4e64a99 100644
--- a/src/external.h
+++ b/src/external.h
@@ -31,7 +31,8 @@ struct external_parameter {
        char *fault_code;
 };
 
-int external_get_action(char *action, char *name, char **value);
+int external_get_action(char *action, char *name, char *arg);
+int external_get_action_data(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);
diff --git a/src/ubus.c b/src/ubus.c
index 719a848..4c741a5 100644
--- a/src/ubus.c
+++ b/src/ubus.c
@@ -5,6 +5,7 @@
  *     (at your option) any later version.
  *
  *     Copyright (C) 2012 Luka Perkov <freecwmp@lukaperkov.net>
+ *     Copyright (C) 2012 Mohamed Kallel <mohamed.kallel@pivasoftware.com>
  */
 
 #include <unistd.h>
@@ -199,11 +200,50 @@ freecwmpd_handle_get_param_values(struct ubus_context 
*ctx, struct ubus_object *
        return 0;
 }
 
+static enum get_param_names {
+       GET_PARAM_NAMES_PARAM,
+       GET_PARAM_NAMES_WRITABLE,
+       GET_PARAM_NAMES_FAULT,
+       __GET_PARAM_NAMES_MAX
+};
+
+static const struct blobmsg_policy get_param_names_policy[] = {
+       [GET_PARAM_NAMES_PARAM] = { .name = "parameter", .type = 
BLOBMSG_TYPE_STRING },
+       [GET_PARAM_NAMES_WRITABLE] = { .name = "writable", .type = 
BLOBMSG_TYPE_STRING },
+       [GET_PARAM_NAMES_FAULT] = { .name = "fault_code", .type = 
BLOBMSG_TYPE_STRING },
+};
+
+static int
+freecwmpd_handle_get_param_names(struct ubus_context *ctx, struct ubus_object 
*obj,
+                       struct ubus_request_data *req, const char *method,
+                       struct blob_attr *msg)
+{
+       struct blob_attr *tb[__GET_PARAM_NAMES_MAX];
+
+       blobmsg_parse(get_param_names_policy, 
ARRAY_SIZE(get_param_names_policy), tb,
+                     blob_data(msg), blob_len(msg));
+
+       if (!tb[GET_PARAM_NAMES_PARAM])
+               return UBUS_STATUS_INVALID_ARGUMENT;
+
+       lfc_log_message(NAME, L_NOTICE,
+                            "triggered ubus get_parameter_names for the 
parameter %s\n",
+                            blobmsg_data(tb[GET_PARAM_NAMES_PARAM]));
+
+       external_add_list_paramameter(blobmsg_data(tb[GET_PARAM_NAMES_PARAM]),
+                       tb[GET_PARAM_NAMES_WRITABLE] ? 
blobmsg_data(tb[GET_PARAM_NAMES_WRITABLE]) : NULL,
+                       NULL,
+                       tb[GET_PARAM_NAMES_FAULT] ? 
blobmsg_data(tb[GET_PARAM_NAMES_FAULT]) : NULL);
+
+       return 0;
+}
+
 static const struct ubus_method freecwmp_methods[] = {
        UBUS_METHOD("notify", freecwmpd_handle_notify, notify_policy),
        UBUS_METHOD("inform", freecwmpd_handle_inform, inform_policy),
        UBUS_METHOD("command", freecwmpd_handle_command, command_policy),
        UBUS_METHOD("get_parameter_values", freecwmpd_handle_get_param_values, 
get_param_values_policy),
+       UBUS_METHOD("get_parameter_names", freecwmpd_handle_get_param_names, 
get_param_names_policy),
 };
 
 static struct ubus_object_type main_object_type =
diff --git a/src/xml.c b/src/xml.c
index d1d1ed9..92fc046 100644
--- a/src/xml.c
+++ b/src/xml.c
@@ -6,6 +6,7 @@
  *
  *     Copyright (C) 2011-2012 Luka Perkov <freecwmp@lukaperkov.net>
  *     Copyright (C) 2012 Jonas Gorski <jogo@openwrt.org>
+ *     Copyright (C) 2012 Mohamed Kallel <mohamed.kallel@pivasoftware.com>
  */
 
 #include <stdbool.h>
@@ -51,6 +52,7 @@ static struct cwmp_namespaces
 const struct rpc_method rpc_methods[] = {
        { "SetParameterValues", xml_handle_set_parameter_values },
        { "GetParameterValues", xml_handle_get_parameter_values },
+       { "GetParameterNames", xml_handle_get_parameter_names },
        { "SetParameterAttributes", xml_handle_set_parameter_attributes },
        { "Download", xml_handle_download },
        { "FactoryReset", xml_handle_factory_reset },
@@ -734,6 +736,114 @@ out:
        return -1;
 }
 
+int xml_handle_get_parameter_names(mxml_node_t *body_in,
+                                   mxml_node_t *tree_in,
+                                   mxml_node_t *tree_out)
+{
+       mxml_node_t *n, *parameter_list, *b = body_in;
+       struct external_parameter *external_parameter;
+       char *parameter_name = NULL;
+       char *next_level = NULL;
+       int counter = 0;
+
+       n = mxmlFindElement(tree_out, tree_out, "soap_env:Body",
+                           NULL, NULL, MXML_DESCEND);
+       if (!n) return -1;
+
+       n = mxmlNewElement(n, "cwmp:GetParameterNamesResponse");
+       if (!n) return -1;
+
+       n = mxmlNewElement(n, "ParameterList");
+       if (!n) return -1;
+
+#ifdef ACS_MULTI
+       mxmlElementSetAttr(n, "xsi:type", "soap_enc:Array");
+#endif
+
+       while (b) {
+               if (b && b->type == MXML_TEXT &&
+                       b->value.text.string &&
+                       b->parent->type == MXML_ELEMENT &&
+                       !strcmp(b->parent->value.element.name, 
"ParameterPath")) {
+                       parameter_name = b->value.text.string;
+               }
+
+               /*
+                * If the ParameterPath node from GetParameterNames does not 
contain child node (txt node)
+                * Then the parameter name is an empty string which means get 
all parameters from the data model
+                */
+               if (b && b->type == MXML_ELEMENT &&
+                       !strcmp(b->value.element.name, "ParameterPath") &&
+                       !b->child) {
+                       parameter_name = "";
+               }
+
+               if (b && b->type == MXML_TEXT &&
+                       b->value.text.string &&
+                       b->parent->type == MXML_ELEMENT &&
+                       !strcmp(b->parent->value.element.name, "NextLevel")) {
+                       next_level = b->value.text.string;
+               }
+               b = mxmlWalkNext(b, body_in, MXML_DESCEND);
+       }
+
+       if (parameter_name && next_level) {
+               if (external_get_action("name", parameter_name, next_level))
+                       goto out;
+       }
+
+       parameter_list = mxmlFindElement(tree_out, tree_out, "ParameterList", 
NULL, NULL, MXML_DESCEND);
+       if (!parameter_list) 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') {
+                       goto out;
+                       //TODO return FAULT message the fault code is in 
external_parameter->fault_cod
+               }
+
+               n = mxmlNewElement(parameter_list, "ParameterInfoStruct");
+               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, "Writable");
+               if (!n) goto out;
+
+               n = mxmlNewText(n, 0, external_parameter->data);
+               if (!n) goto out;
+
+               counter++;
+
+               external_parameter_delete(external_parameter);
+       }
+
+#ifdef ACS_MULTI
+       char *c;
+       b = mxmlFindElement(tree_out, tree_out, "ParameterList", 
+                           NULL, NULL, MXML_DESCEND);
+       if (!b) goto out;
+
+       if (asprintf(&c, "cwmp:ParameterInfoStruct[%d]", counter) == -1)
+               goto out;
+
+       mxmlElementSetAttr(b, "soap_enc:arrayType", c);
+       FREE(c);
+#endif
+
+       return 0;
+
+out:
+       external_free_list_parameter();
+       return -1;
+}
+
 static int xml_handle_set_parameter_attributes(mxml_node_t *body_in,
                                               mxml_node_t *tree_in,
                                               mxml_node_t *tree_out) {
diff --git a/src/xml.h b/src/xml.h
index 8f63192..a9191eb 100644
--- a/src/xml.h
+++ b/src/xml.h
@@ -26,6 +26,10 @@ static int xml_handle_get_parameter_values(mxml_node_t 
*body_in,
                                           mxml_node_t *tree_in,
                                           mxml_node_t *tree_out);
 
+static int xml_handle_get_parameter_names(mxml_node_t *body_in,
+                                          mxml_node_t *tree_in,
+                                          mxml_node_t *tree_out);
+
 static int xml_handle_set_parameter_attributes(mxml_node_t *body_in,
                                               mxml_node_t *tree_in,
                                               mxml_node_t *tree_out);
-- 
1.7.4.1


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