Hi,

On Fri, 2012-09-07 at 17:26 -0700, Tudor Marcu wrote:
> The services section handles all of the dbus parsing and appending in order
> to manipulate services. The function set_service_property  is responsible for
> configuring properties that contain an array or dictionary. Functions are
> provided for iterating through connman's dbus messages and extracting the
> properties in a useful manner. Specific properties can be appended to messages
> to send to connman with the append functions. A couple functions such as find
> service are given to provide more flexibility in user input.
> ---
>  client/services.c |  486 
> +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  client/services.h |   58 +++++++
>  2 files changed, 544 insertions(+)
>  create mode 100644 client/services.c
>  create mode 100644 client/services.h
> 
> diff --git a/client/services.c b/client/services.c
> new file mode 100644
> index 0000000..b5fe6d3
> --- /dev/null
> +++ b/client/services.c
> @@ -0,0 +1,486 @@
> +/*
> + *
> + *  Connection Manager
> + *
> + *  Copyright (C) 2012  Intel Corporation. All rights reserved.
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License version 2 as
> + *  published by the Free Software Foundation.
> + *
> + *  This program is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with this program; if not, write to the Free Software
> + *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  
> USA
> + *
> + */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <stdint.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include <errno.h>
> +
> +#include "client/services.h"
> +#include "connman.h"
> +
> +static void append_property_array(DBusMessageIter *iter, char *property,
> +                                             char **data, int num_args)
> +{
> +     DBusMessageIter value, array;
> +     int i;
> +
> +     dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &property);
> +
> +     connman_dbus_array_open(iter, &value);
> +     dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
> +                                      DBUS_TYPE_STRING_AS_STRING, &array);
> +
> +     for (i = 0; i < num_args; i++) {
> +             dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING,
> +                                             &data[i]);
> +             printf("Added: %s\n", data[i]);
> +     }
> +     dbus_message_iter_close_container(&value, &array);
> +     dbus_message_iter_close_container(iter, &value);
> +}
> +
> +static void append_property_dict(DBusMessageIter *iter, char *property,
> +                                     char **keys, char **data, int num_args)
> +{
> +     DBusMessageIter value, dict, entry, dict_key;
> +     int i;
> +     unsigned char prefix;
> +
> +     dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &property);
> +
> +     /* Top most level is a{sv} */
> +     connman_dbus_dict_open_variant(iter, &value);
> +
> +     connman_dbus_dict_open(&value, &dict);
> +
> +     for (i = 0; i < num_args; i++) {
> +             dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
> +                                                     NULL, &entry);
> +             dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING,
> +                                                     &keys[i]);
> +
> +             if (strcmp(property, "IPv6.Configuration") == 0 && i == 2) {

As keys[i] and data[i] go hand in hand(?), please check for
'g_strcmp0(keys[i], "PrefixLength")' instead of a magic number 2 here.

> +                     prefix = atoi(data[i]);

atoi() crashes if fed a NULL...

> +
> +                     dbus_message_iter_open_container(&entry,
> +                                             DBUS_TYPE_VARIANT,
> +                                             DBUS_TYPE_BYTE_AS_STRING,
> +                                             &dict_key);
> +                     dbus_message_iter_append_basic(&dict_key,
> +                                                    DBUS_TYPE_BYTE, &prefix);
> +             } else {
> +                     dbus_message_iter_open_container(&entry,
> +                                              DBUS_TYPE_VARIANT,
> +                                              DBUS_TYPE_STRING_AS_STRING,
> +                                              &dict_key);
> +                     dbus_message_iter_append_basic(&dict_key,
> +                                                     DBUS_TYPE_STRING,
> +                                                     &data[i]);
> +             }
> +             dbus_message_iter_close_container(&entry, &dict_key);
> +             dbus_message_iter_close_container(&dict, &entry);
> +     }
> +     /* Close {sv}, then close a{sv} */
> +     connman_dbus_dict_close(&value, &dict);
> +     connman_dbus_dict_close(iter, &value);
> +}
> +
> +void iterate_array(DBusMessageIter *iter)
> +{
> +     DBusMessageIter array_item;
> +     dbus_bool_t key_bool;
> +     char *key_str;
> +
> +     dbus_message_iter_recurse(iter, &array_item);
> +     /* Make sure the entry is not NULL! */
> +     printf("[ ");
> +     while (dbus_message_iter_get_arg_type(&array_item) !=
> +                                     DBUS_TYPE_INVALID) {
> +             if (dbus_message_iter_get_arg_type(&array_item) ==
> +                                     DBUS_TYPE_STRING) {
> +                     dbus_message_iter_get_basic(&array_item,
> +                                             &key_str);
> +                     printf("%s ", key_str);
> +             } else if (dbus_message_iter_get_arg_type(&array_item) ==
> +                                     DBUS_TYPE_BOOLEAN) {
> +                     dbus_message_iter_get_basic(&array_item, &key_bool);
> +                     printf("%s ", key_bool == TRUE ? "True"
> +                                             : "False");
> +             }
> +             dbus_message_iter_next(&array_item);
> +     }
> +     if (dbus_message_iter_get_arg_type(&array_item) ==
> +                                     DBUS_TYPE_INVALID)
> +             printf("] ");
> +}
> +
> +void iterate_dict(DBusMessageIter *dict, char *string, uint16_t key_int)
> +{
> +     DBusMessageIter dict_entry, sub_dict_entry;
> +
> +     printf("{ ");
> +     while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
> +             dbus_message_iter_recurse(dict, &dict_entry);
> +             dbus_message_iter_get_basic(&dict_entry, &string);
> +             printf("%s=", string);
> +             dbus_message_iter_next(&dict_entry);
> +             while (dbus_message_iter_get_arg_type(&dict_entry)
> +                                                     != DBUS_TYPE_INVALID) {
> +                     dbus_message_iter_recurse(&dict_entry, &sub_dict_entry);
> +                     if (dbus_message_iter_get_arg_type(&sub_dict_entry)
> +                                                     == DBUS_TYPE_UINT16) {
> +                             dbus_message_iter_get_basic(&sub_dict_entry,
> +                                                             &key_int);
> +                             printf("%d ", key_int);
> +                     } else if 
> (dbus_message_iter_get_arg_type(&sub_dict_entry)
> +                                                     == DBUS_TYPE_STRING) {
> +                             dbus_message_iter_get_basic(&sub_dict_entry,
> +                                                             &string);
> +                             printf("%s ", string);
> +                     } else if 
> (dbus_message_iter_get_arg_type(&sub_dict_entry)
> +                                                     == DBUS_TYPE_ARRAY) {
> +                             iterate_array(&sub_dict_entry);
> +                     }
> +                     dbus_message_iter_next(&dict_entry);
> +             }
> +             dbus_message_iter_next(dict);
> +     }
> +     printf("}");
> +}
> +
> +/* Get dictionary info about the current service and store it */
> +static void extract_service_properties(DBusMessageIter *dict,
> +                             struct service_data *service)
> +{
> +     DBusMessageIter entry, value, array_item;
> +     char *key;
> +     char *key_str;
> +     uint16_t key_uint16;
> +     dbus_bool_t key_bool;
> +
> +     while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
> +             dbus_message_iter_recurse(dict, &entry);
> +             dbus_message_iter_get_basic(&entry, &key);
> +             printf("\n  %s = ", key);
> +             if (strcmp(key, "Name") == 0 && strlen(key) < 5)
> +                     service->name = key;
> +
> +             dbus_message_iter_next(&entry);
> +             dbus_message_iter_recurse(&entry, &value);
> +             /* Check if entry is a dictionary itself */
> +             if (strcmp(key, "Ethernet") == 0 ||
> +                     /* if just strcmp, the .Configuration names don't match
> +                      * and they are iterated with iterate_array instead*/
> +                             strncmp(key, "IPv4", 4) == 0 ||
> +                             strncmp(key, "IPv6", 4) == 0 ||
> +                             strncmp(key, "Proxy", 5) == 0 ||
> +                             strcmp(key, "Provider") == 0) {
> +                     dbus_message_iter_recurse(&value, &array_item);
> +                     iterate_dict(&array_item, key_str, key_uint16);
> +             } else
> +             switch (dbus_message_iter_get_arg_type(&value)) {
> +             case DBUS_TYPE_ARRAY:
> +                     iterate_array(&value);
> +                     break;
> +             case DBUS_TYPE_BOOLEAN:
> +                     dbus_message_iter_get_basic(&value, &key_bool);
> +                     printf("%s", key_bool == TRUE ? "True" : "False");
> +                     break;
> +             case DBUS_TYPE_BYTE:
> +                     dbus_message_iter_get_basic(&value, &key_uint16);
> +                     printf("%d", key_uint16);
> +                     break;
> +             case DBUS_TYPE_STRING:
> +                     dbus_message_iter_get_basic(&value, &key_str);
> +                     printf("%s", key_str);
> +                     break;
> +             }
> +             dbus_message_iter_next(dict);
> +     }
> +     printf("\n\n");
> +}
> +
> +static void match_service_name(DBusMessage *message, char *service_name,
> +                                             struct service_data *service)
> +{
> +     DBusMessageIter iter, array;
> +
> +     dbus_message_iter_init(message, &iter);
> +     dbus_message_iter_recurse(&iter, &array);
> +
> +     while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
> +             DBusMessageIter entry, dict;
> +             char *path;
> +
> +             dbus_message_iter_recurse(&array, &entry);
> +             dbus_message_iter_get_basic(&entry, &path);
> +
> +             service->path = strip_service_path(path);
> +             dbus_message_iter_next(&entry);
> +             dbus_message_iter_recurse(&entry, &dict);
> +             extract_service_name(&dict, service);
> +             if (g_strcmp0(service_name, service->name) == 0) {
> +                     printf("    Matched %s with %s\n\n", service->name,
> +                                                             service->path);
> +                     break;
> +             }
> +             dbus_message_iter_next(&array);
> +     }
> +}
> +
> +void extract_service_name(DBusMessageIter *dict, struct service_data 
> *service)
> +{
> +     DBusMessageIter dict_entry, value;
> +     const char *key;
> +     const char *state;
> +
> +     while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
> +             dbus_message_iter_recurse(dict, &dict_entry);
> +             dbus_message_iter_get_basic(&dict_entry, &key);
> +             if (strcmp(key, "Name") == 0 && strlen(key) < 5) {

The 'strlen(key) < 5' doesn't look useful here.

> +                     dbus_message_iter_next(&dict_entry);
> +                     dbus_message_iter_recurse(&dict_entry, &value);
> +                     dbus_message_iter_get_basic(&value, &service->name);
> +             }
> +             if (strcmp(key, "AutoConnect") == 0) {
> +                     dbus_message_iter_next(&dict_entry);
> +                     dbus_message_iter_recurse(&dict_entry, &value);
> +                     dbus_message_iter_get_basic(&value, &service->autoconn);
> +             }
> +             if (strcmp(key, "State") == 0) {
> +                     dbus_message_iter_next(&dict_entry);
> +                     dbus_message_iter_recurse(&dict_entry, &value);
> +                     dbus_message_iter_get_basic(&value, &state);
> +                     if (strcmp(state, "ready") == 0)
> +                             service->connected = TRUE;
> +                     else if (strcmp(state, "online") == 0)
> +                             service->online = TRUE;
> +                     else {
> +                             service->connected = FALSE;
> +                             service->online = FALSE;
> +                     }
> +             }
> +             if (strcmp(key, "Favorite") == 0) {
> +                     dbus_message_iter_next(&dict_entry);
> +                     dbus_message_iter_recurse(&dict_entry, &value);
> +                     dbus_message_iter_get_basic(&value, &service->favorite);
> +             }
> +             dbus_message_iter_next(dict);
> +     }
> +}
> +
> +/* Show detailed information about a service */
> +void extract_services(DBusMessage *message, char *service_name)
> +{
> +     DBusMessageIter iter, array;
> +
> +     dbus_message_iter_init(message, &iter);
> +     dbus_message_iter_recurse(&iter, &array);
> +
> +     while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
> +             DBusMessageIter entry, dict;
> +             struct service_data service;
> +             char *path;
> +
> +             dbus_message_iter_recurse(&array, &entry);
> +             dbus_message_iter_get_basic(&entry, &path);
> +
> +             service.path = strip_service_path(path);
> +             if (g_strcmp0(service.path, service_name) == 0) {
> +                     printf("[ %s ]\n", service.path);
> +                     dbus_message_iter_next(&entry);
> +                     dbus_message_iter_recurse(&entry, &dict);
> +                     extract_service_properties(&dict, &service);
> +             }
> +             dbus_message_iter_next(&array);
> +     }
> +}
> +
> +/* Support both string names and path names for connecting to services */
> +char *strip_service_path(char *service)
> +{
> +     char *service_name;
> +     service_name = strrchr(service, '/');
> +     if (service_name == NULL)
> +             return service;
> +     else
> +             return service_name + 1;
> +}
> +
> +/* Show a simple list of service names only */
> +void get_services(DBusMessage *message)
> +{
> +     DBusMessageIter iter, array;
> +
> +     dbus_message_iter_init(message, &iter);
> +     dbus_message_iter_recurse(&iter, &array);
> +
> +     while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
> +             DBusMessageIter entry, dict;
> +             struct service_data service;
> +             char *path;
> +
> +             dbus_message_iter_recurse(&array, &entry);
> +             dbus_message_iter_get_basic(&entry, &path);
> +
> +             service.path = strip_service_path(path);
> +             dbus_message_iter_next(&entry);
> +             dbus_message_iter_recurse(&entry, &dict);
> +             extract_service_name(&dict, &service);
> +             printf("%-1s%-1s%-1s %-20s { %s }\n",
> +                     service.favorite ? "*" : "",
> +                     service.autoconn ? "A" : "",
> +                     service.online ? "O" : (service.connected ? "R" : ""),
> +                     service.name, service.path);
> +             dbus_message_iter_next(&array);
> +     }
> +}
> +
> +const char *find_service(DBusConnection *connection, DBusMessage *message,
> +                       char *service_name, struct service_data *service)
> +{
> +     DBusMessageIter iter, array, entry;
> +     char *path;
> +
> +     service_name = strip_service_path(service_name);
> +     match_service_name(message, service_name, service);
> +     /* Service name did not match, so check if entry is a path */
> +     if (g_strcmp0(service_name, service->name)) {
> +             dbus_message_iter_init(message, &iter);
> +             dbus_message_iter_recurse(&iter, &array);
> +
> +             while (dbus_message_iter_get_arg_type(&array) ==
> +                                                     DBUS_TYPE_STRUCT) {
> +                     dbus_message_iter_recurse(&array, &entry);
> +                     dbus_message_iter_get_basic(&entry, &path);
> +
> +                     service->path = strip_service_path(path);
> +                     if (g_strcmp0(service->path, service_name) == 0)
> +                             return service->path;
> +                     dbus_message_iter_next(&array);
> +             }
> +             fprintf(stderr, "'%s' is not a valid service name or path.\n",
> +                                                             service_name);
> +             fprintf(stderr, "Use the 'services' command to find available "
> +                                                     "services.\n");
> +             return NULL;
> +     } else
> +             return service->path;
> +}
> +
> +int set_proxy_manual(DBusConnection *connection, DBusMessage *message,
> +                             char *name, char **servers, char **excludes,
> +                             int num_servers, int num_excludes)
> +{
> +     DBusMessage *message_send;
> +     DBusMessageIter iter, value, dict, entry, data;
> +     struct service_data service;
> +     char *path;
> +     const char *path_name;
> +     char *property = "Proxy.Configuration";
> +     char *method = "Method";
> +     char *manual = "manual";
> +
> +     path_name = find_service(connection, message, name, &service);
> +     if (path_name == NULL)
> +             return -ENXIO;
> +
> +     path = g_strdup_printf("/net/connman/service/%s", path_name);
> +     message_send = dbus_message_new_method_call("net.connman", path,
> +                                                     "net.connman.Service",
> +                                                     "SetProperty");
> +
> +     if (message_send == NULL)
> +             return -ENOMEM;
> +
> +     dbus_message_iter_init_append(message_send, &iter);
> +     dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property);
> +     connman_dbus_dict_open_variant(&iter, &value);
> +     connman_dbus_dict_open(&value, &dict);
> +     dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL,
> +                                                     &entry);
> +     dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &method);
> +     dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
> +                                             DBUS_TYPE_STRING_AS_STRING,
> +                                             &data);
> +     dbus_message_iter_append_basic(&data, DBUS_TYPE_STRING, &manual);
> +     dbus_message_iter_close_container(&entry, &data);
> +     dbus_message_iter_close_container(&dict, &entry);
> +     dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL,
> +                                                     &entry);
> +     append_property_array(&entry, "Servers", servers, num_servers);
> +     dbus_message_iter_close_container(&dict, &entry);
> +
> +     if (num_excludes != 0) {
> +             dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
> +                                                     NULL, &entry);
> +             append_property_array(&entry, "Excludes", excludes,
> +                                                     num_excludes);
> +             dbus_message_iter_close_container(&dict, &entry);
> +     }
> +
> +     dbus_message_iter_close_container(&value, &dict);
> +     dbus_message_iter_close_container(&iter, &value);
> +     dbus_connection_send(connection, message_send, NULL);
> +     dbus_connection_flush(connection);
> +     dbus_message_unref(message_send);
> +
> +     return 0;
> +}
> +
> +int set_service_property(DBusConnection *connection, DBusMessage *message,
> +                             char *name, char *property, char **keys,
> +                             void *data, int num_args)
> +{
> +     DBusMessage *message_send;
> +     DBusMessageIter iter;
> +     struct service_data service;
> +     char *path;
> +     const char *path_name;
> +
> +     path_name = find_service(connection, message, name, &service);
> +     if (path_name == NULL)
> +             return -ENXIO;
> +
> +     path = g_strdup_printf("/net/connman/service/%s", path_name);
> +     message_send = dbus_message_new_method_call("net.connman", path,
> +                                                     "net.connman.Service",
> +                                                     "SetProperty");
> +
> +     if (message_send == NULL)
> +             return -ENOMEM;
> +
> +     dbus_message_iter_init_append(message_send, &iter);
> +
> +     if (strcmp(property, "AutoConnect") == 0)
> +             connman_dbus_property_append_basic(&iter,
> +                                             (const char *) property,
> +                                             DBUS_TYPE_BOOLEAN, data);
> +     else if ((strcmp(property, "Domains.Configuration") == 0)
> +                     || (strcmp(property, "Timeservers.Configuration") == 0)
> +                     || (strcmp(property, "Nameservers.Configuration") == 0))
> +             append_property_array(&iter, property, data, num_args);
> +     else if ((strcmp(property, "IPv4.Configuration") == 0)
> +                     || (strcmp(property, "IPv6.Configuration") == 0)
> +                     || (strcmp(property, "Proxy.Configuration") == 0))
> +             append_property_dict(&iter, property, keys, data, num_args);
> +
> +     dbus_connection_send(connection, message_send, NULL);
> +     dbus_connection_flush(connection);
> +     dbus_message_unref(message_send);
> +     g_free(path);
> +
> +     return 0;
> +}

> +

Extra empty line end of file, please remove since 'git am' doesn't like
it at all.

> diff --git a/client/services.h b/client/services.h
> new file mode 100644
> index 0000000..177de19
> --- /dev/null
> +++ b/client/services.h
> @@ -0,0 +1,58 @@
> +/*
> + *
> + *  Connection Manager
> + *
> + *  Copyright (C) 2012  Intel Corporation. All rights reserved.
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License version 2 as
> + *  published by the Free Software Foundation.
> + *
> + *  This program is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with this program; if not, write to the Free Software
> + *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  
> USA
> + *
> + */
> +#ifndef __CLIENT_SERVICES_H
> +#define __CLIENT_SERVICES_H
> +
> +#include <stdint.h>
> +
> +#include <dbus/dbus.h>
> +
> +struct service_data {
> +     const char *path;
> +     const char *name;
> +     dbus_bool_t autoconn;
> +     dbus_bool_t favorite;
> +     dbus_bool_t connected;
> +     dbus_bool_t online;
> +};
> +
> +char *strip_service_path(char *service);
> +void extract_service_name(DBusMessageIter *dict, struct service_data 
> *service);
> +int set_service_property(DBusConnection *connection, DBusMessage *message,
> +                             char *name, char *property, char **keys,
> +                             void *data, int num_args);
> +int set_proxy_manual(DBusConnection *connection, DBusMessage *message,
> +                             char *name, char **servers, char **excludes,
> +                             int num_servers, int num_excludes);
> +
> +const char *find_service(DBusConnection *connection, DBusMessage *message,
> +                       char *service_name, struct service_data *service);
> +void extract_services(DBusMessage *message, char *service_name);
> +void get_services(DBusMessage *message);
> +void iterate_dict(DBusMessageIter *dict, char *string, uint16_t key_int);
> +int list_services(DBusConnection *connection, char *function);
> +int list_services_properties(DBusConnection *connection, char *function,
> +                             char *service_name);
> +int listen_for_service_signal(DBusConnection *connection, char *signal_name,
> +                     char *service_name);
> +void iterate_array(DBusMessageIter *iter);
> +#endif

> +

Extra empty line end of file, please remove.


Cheers,

        Patrik


_______________________________________________
connman mailing list
[email protected]
http://lists.connman.net/listinfo/connman

Reply via email to