The point here is to create a virtual configuration, which does not come
from a real file. This is a handy way for plugins to be able to provision
services without creating any file on the FS.

In case of a wifi configuration type and if connect is requested, it will
trigger a scan, thus leading to a possible service being provisioned by
such virtual configuration. If so and if connect was requested: the service
will be asked to connect.
---
 include/provision.h |  1 +
 src/config.c        | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 91 insertions(+), 2 deletions(-)

diff --git a/include/provision.h b/include/provision.h
index d6d7c72..b5f736e 100644
--- a/include/provision.h
+++ b/include/provision.h
@@ -42,6 +42,7 @@ struct connman_config_entry {
        connman_bool_t hidden;
 };
 
+int connman_config_provision_mutable_service(GKeyFile *keyfile);
 struct connman_config_entry **connman_config_get_entries(const char *type);
 void connman_config_free_entries(struct connman_config_entry **entries);
 
diff --git a/src/config.c b/src/config.c
index 098ef61..a4f4c58 100644
--- a/src/config.c
+++ b/src/config.c
@@ -56,6 +56,8 @@ struct connman_config_service {
        char *config_ident; /* file prefix */
        char *config_entry; /* entry name */
        connman_bool_t hidden;
+       connman_bool_t virtual;
+       char *virtual_file;
        char *ipv4_address;
        char *ipv4_netmask;
        char *ipv4_gateway;
@@ -173,6 +175,9 @@ static void unregister_service(gpointer data)
        protected_services = g_slist_remove(protected_services,
                                                config_service);
 
+       if (config_service->virtual == TRUE)
+               goto free_only;
+
        for (list = config_service->service_identifiers; list != NULL;
                                                        list = list->next) {
                service_id = list->data;
@@ -238,6 +243,7 @@ free_only:
        g_slist_free_full(config_service->service_identifiers, g_free);
        g_free(config_service->config_ident);
        g_free(config_service->config_entry);
+       g_free(config_service->virtual_file);
        g_free(config_service);
 }
 
@@ -1021,6 +1027,15 @@ static void provision_service_wifi(gpointer key,
                __connman_service_set_hidden(service);
 }
 
+static gboolean remove_virtual_config(gpointer user_data)
+{
+       const char *virtual_file = user_data;
+
+       g_hash_table_remove(config_table, virtual_file);
+
+       return FALSE;
+}
+
 static void provision_service(gpointer key, gpointer value,
                                                        gpointer user_data)
 {
@@ -1157,7 +1172,8 @@ static void provision_service(gpointer key, gpointer 
value,
                g_slist_prepend(config->service_identifiers,
                                g_strdup(service_id));
 
-       __connman_service_set_immutable(service, TRUE);
+       if (config->virtual == FALSE)
+               __connman_service_set_immutable(service, TRUE);
 
        __connman_service_set_favorite_delayed(service, TRUE, TRUE);
 
@@ -1197,7 +1213,11 @@ static void provision_service(gpointer key, gpointer 
value,
 
        __connman_service_save(service);
 
-       __connman_service_auto_connect();
+       if (config->virtual == TRUE) {
+               __connman_service_connect(service);
+               g_timeout_add(0, remove_virtual_config, config->virtual_file);
+       } else
+               __connman_service_auto_connect();
 }
 
 int __connman_config_provision_service(struct connman_service *service)
@@ -1294,6 +1314,74 @@ int __connman_config_provision_service_ident(struct 
connman_service *service,
        return ret;
 }
 
+static void generate_random_string(char *str, int length)
+{
+       uint8_t val;
+       int i;
+
+       memset(str, '\0', length);
+
+       for (i = 0; i < length-1; i++) {
+               do {
+                       val = (uint8_t)(random() % 122);
+                       if (val < 48)
+                               val += 48;
+               } while((val > 57 && val < 65) || (val > 90 && val < 97));
+
+               str[i] = val;
+       }
+}
+
+int connman_config_provision_mutable_service(GKeyFile *keyfile)
+{
+       struct connman_config_service *service_config;
+       struct connman_config *config;
+       char *vfile, *group;
+       char rstr[11];
+
+       DBG("");
+
+       generate_random_string(rstr, 11);
+
+       vfile = g_strdup_printf("service_mutable_%s.config", rstr);
+
+       config = create_config(vfile);
+       if (config == NULL)
+               return -ENOMEM;
+
+       if (load_service_from_keyfile(keyfile, config) == FALSE)
+               goto error;
+
+       group = g_key_file_get_start_group(keyfile);
+
+       service_config = g_hash_table_lookup(config->service_table, group+8);
+       if (service_config == NULL)
+               goto error;
+
+       /* Specific to non file based config: */
+       g_free(service_config->config_ident);
+       service_config->config_ident = NULL;
+       g_free(service_config->config_entry);
+       service_config->config_entry = NULL;
+
+       service_config->virtual = TRUE;
+       service_config->virtual_file = vfile;
+
+       __connman_service_provision_changed(vfile);
+
+       if (g_strcmp0(service_config->type, "wifi") == 0)
+               __connman_device_request_scan(CONNMAN_SERVICE_TYPE_WIFI);
+
+       return 0;
+
+error:
+       DBG("Could not proceed");
+       g_hash_table_remove(config_table, vfile);
+       g_free(vfile);
+
+       return -EINVAL;
+}
+
 struct connman_config_entry **connman_config_get_entries(const char *type)
 {
        GHashTableIter iter_file, iter_config;
-- 
1.8.1.2

_______________________________________________
connman mailing list
connman@connman.net
http://lists.connman.net/listinfo/connman

Reply via email to