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