From 8d7aa581006b99460a15e5ff4df19ef2ec9a59ff Mon Sep 17 00:00:00 2001 From: Ludovic Ferrandis Date: Wed, 11 Sep 2013 15:10:18 +0200 Subject: [Settings] Update: Save, monitoring, notification Make settings & white list independant. Settings doesn't call directly WhiteList API. Settings 'never_quit' & 'netf_enabled' & 'netf_entries' are now save to the settings file when set using the new API below: - dleyna-settings_set_never_quit - dleyna_settings_set_white_list_enabled - dleyna_settings_set_white_list_entries Monitoring has been removed. Signed-off-by: Ludovic Ferrandis --- libdleyna/core/settings.c | 320 ++++++++++++++++++++------------------------ libdleyna/core/settings.h | 18 ++- libdleyna/core/white-list.c | 85 +++++++----- libdleyna/core/white-list.h | 20 +-- 4 files changed, 217 insertions(+), 226 deletions(-) diff --git a/libdleyna/core/settings.c b/libdleyna/core/settings.c index c86ace9..42ae27c 100644 --- a/libdleyna/core/settings.c +++ b/libdleyna/core/settings.c @@ -29,10 +29,8 @@ struct dleyna_settings_t_ { GKeyFile *keyfile; - GFileMonitor *monitor; - gulong handler_id; - guint ev_id; gchar *file_name; + gchar *file_path; /* Global section */ gboolean never_quit; @@ -64,34 +62,37 @@ struct dleyna_settings_t_ { #define DLEYNA_SETTINGS_DEFAULT_LOG_TYPE DLEYNA_LOG_TYPE #define DLEYNA_SETTINGS_DEFAULT_LOG_LEVEL DLEYNA_LOG_LEVEL +#if DLEYNA_LOG_LEVEL & DLEYNA_LOG_LEVEL_INFO #define DLEYNA_SETTINGS_LOG_KEYS(sys, loc, settings) \ do { \ gchar *str = NULL; \ \ DLEYNA_LOG_DEBUG_NL(); \ - DLEYNA_LOG_INFO("Load file [%s]", loc ? loc : sys); \ + DLEYNA_LOG_INFO("Load file [%s]", (settings)->file_path); \ DLEYNA_LOG_DEBUG_NL(); \ \ - DLEYNA_LOG_DEBUG("[General settings]"); \ - DLEYNA_LOG_DEBUG("Never Quit: %s", (settings)->never_quit ? "T" : "F");\ + DLEYNA_LOG_INFO("[General settings]"); \ + DLEYNA_LOG_INFO("Never Quit: %s", (settings)->never_quit ? "T" : "F");\ DLEYNA_LOG_DEBUG_NL(); \ - DLEYNA_LOG_DEBUG("Connector Name: %s", (settings)->connector_name);\ + DLEYNA_LOG_INFO("Connector Name: %s", (settings)->connector_name);\ DLEYNA_LOG_DEBUG_NL(); \ \ - DLEYNA_LOG_DEBUG("[Logging settings]"); \ - DLEYNA_LOG_DEBUG("Log Type : %d", (settings)->log_type); \ - DLEYNA_LOG_DEBUG("Log Level: 0x%02X", (settings)->log_level); \ + DLEYNA_LOG_INFO("[Logging settings]"); \ + DLEYNA_LOG_INFO("Log Type : %d", (settings)->log_type); \ + DLEYNA_LOG_INFO("Log Level: 0x%02X", (settings)->log_level); \ DLEYNA_LOG_DEBUG_NL(); \ \ if ((settings)->netf_entries != NULL) \ str = g_variant_print((settings)->netf_entries, FALSE); \ - DLEYNA_LOG_DEBUG("[Network filtering settings]"); \ - DLEYNA_LOG_DEBUG("Enabled : %s", (settings)->netf_enabled ? "T" : "F");\ - DLEYNA_LOG_DEBUG("Entries: %s", str); \ + DLEYNA_LOG_INFO("[Network filtering settings]"); \ + DLEYNA_LOG_INFO("Enabled : %s", (settings)->netf_enabled ? "T" : "F");\ + DLEYNA_LOG_INFO("Entries: %s", str); \ g_free(str); \ DLEYNA_LOG_DEBUG_NL(); \ } while (0) - +#else +#define DLEYNA_SETTINGS_LOG_KEYS(sys, loc, settings) +#endif static void prv_get_keyfile_path(const gchar *file, gchar **sys_path, gchar **loc_path) @@ -159,7 +160,8 @@ static GKeyFile *prv_load_keyfile(const gchar *filepath) keyfile = g_key_file_new(); - if (!g_key_file_load_from_file(keyfile, filepath, G_KEY_FILE_NONE, + if (!g_key_file_load_from_file(keyfile, filepath, + G_KEY_FILE_KEEP_COMMENTS, NULL)) { g_key_file_free(keyfile); keyfile = NULL; @@ -344,15 +346,20 @@ static void prv_keyfile_init(dleyna_settings_t *settings, const gchar *sys_path, const gchar *loc_path) { + const gchar *path = loc_path; + settings->keyfile = prv_load_keyfile(loc_path); - if (settings->keyfile == NULL) + if (settings->keyfile == NULL) { + path = sys_path; settings->keyfile = prv_load_keyfile(sys_path); + } if (settings->keyfile != NULL) { prv_read_keys(settings); dleyna_log_update_type_level(settings->log_type, settings->log_level); + settings->file_path = g_strdup(path); } } @@ -367,154 +374,75 @@ static void prv_keyfile_finalize(dleyna_settings_t *settings) g_key_file_free(settings->keyfile); settings->keyfile = NULL; } -} - -static gboolean prv_netf_entries_are_equal(GVariant *old, GVariant *new) -{ - gboolean match; - GVariantIter iter1; - GVariantIter iter2; - gchar *entry1; - gchar *entry2; - - match = (old == new); - if (match || - ((old == NULL) && (new != NULL)) || - ((old != NULL) && (new == NULL))) - goto exit; - - (void) g_variant_iter_init(&iter1, old); - - while (g_variant_iter_next(&iter1, "&s", &entry1)) { - (void) g_variant_iter_init(&iter2, new); - - while (g_variant_iter_next(&iter2, "&s", &entry2) && !match) - match = !strcmp(entry1, entry2); - - if (!match) - break; - } - -exit: - return match; + g_free(settings->file_path); + settings->file_path = NULL; } -static void prv_reload(dleyna_settings_t *settings) +void dleyna_settings_new(const gchar *server, dleyna_settings_t **settings) { gchar *sys_path = NULL; gchar *loc_path = NULL; - gboolean saved_netf_enabled; - GVariant *saved_netf_entries; - GVariant *netf_entries; + const gchar *server_name; - DLEYNA_LOG_INFO("Reload local configuration file"); + *settings = g_malloc0(sizeof(**settings)); - /* Save all White List information */ - saved_netf_enabled = settings->netf_enabled; - saved_netf_entries = settings->netf_entries; - /* Prevent prv_keyfile_finalize()) to free it */ - settings->netf_entries = NULL; + server_name = strrchr(server, '/'); + if (server_name) + server_name++; + else + server_name = server; - prv_keyfile_finalize(settings); - prv_init_default(settings); - prv_get_keyfile_path(settings->file_name, &sys_path, &loc_path); + (*settings)->file_name = g_strdup_printf("%s%s", server_name, ".conf"); - if (sys_path || loc_path) - prv_keyfile_init(settings, sys_path, loc_path); - - netf_entries = settings->netf_entries; - - /* FIXME: Block white list signals instead */ - /* A little optimization hack: - * 1 - Updating the wl list has no effect if the wl is disabled. - * 2 - If the enabled settings has changed to disabled, apply first. - * 3 - If it has changed to enabled, update the list first, then - * apply the change last. - */ - if (!settings->netf_enabled && saved_netf_enabled) - dleyna_white_list_enable(settings->netf_enabled, TRUE); - - /* Remove old entries if new ones are different. - * Don't clear() to avoid to loose entries added by a client - */ - if (!prv_netf_entries_are_equal(saved_netf_entries, netf_entries)) { - dleyna_white_list_remove_entries(saved_netf_entries, FALSE); - dleyna_white_list_add_entries(netf_entries, TRUE); - } + prv_init_default(*settings); - if (settings->netf_enabled && !saved_netf_enabled) - dleyna_white_list_enable(settings->netf_enabled, TRUE); + prv_get_keyfile_path((*settings)->file_name, &sys_path, &loc_path); + + if (loc_path) + prv_check_local_keyfile(sys_path, loc_path); - if (saved_netf_entries != NULL) - g_variant_unref(saved_netf_entries); + if (sys_path || loc_path) + prv_keyfile_init(*settings, sys_path, loc_path); - DLEYNA_SETTINGS_LOG_KEYS(sys_path, loc_path, settings); + DLEYNA_SETTINGS_LOG_KEYS(sys_path, loc_path, *settings); g_free(sys_path); g_free(loc_path); } -static gboolean prv_monitor_timout_cb(gpointer user_data) +void dleyna_settings_delete(dleyna_settings_t *settings) { - dleyna_settings_t *data = (dleyna_settings_t *)user_data; - - DLEYNA_LOG_INFO("Change in local settings file: Reload"); + g_free(settings->connector_name); + g_free(settings->file_name); - prv_reload(data); + prv_keyfile_finalize(settings); - data->ev_id = 0; - return FALSE; + g_free(settings); } -static void prv_monitor_keyfile_cb(GFileMonitor *monitor, - GFile *file, - GFile *other_file, - GFileMonitorEvent event_type, - gpointer user_data) +const gchar *dleyna_settings_connector_name(dleyna_settings_t *settings) { - dleyna_settings_t *data = (dleyna_settings_t *)user_data; - - switch (event_type) { - case G_FILE_MONITOR_EVENT_CHANGED: - case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: - case G_FILE_MONITOR_EVENT_DELETED: - case G_FILE_MONITOR_EVENT_CREATED: - case G_FILE_MONITOR_EVENT_MOVED: - /* Reset the timer to prevent running the cb if monitoring - * event are raised 1 sec after the timer has been set */ - if (data->ev_id != 0) - (void) g_source_remove(data->ev_id); - - data->ev_id = g_timeout_add_seconds(1, - prv_monitor_timout_cb, - user_data); - break; - default: - break; - } + return settings->connector_name; } -static void prv_monitor_local_keyfile(dleyna_settings_t *settings, - const gchar *loc_path) +static void prv_save_settings_to_file(dleyna_settings_t *settings, + GError **error) { - GFile *loc_file; - GFileMonitor *monitor = NULL; - gulong handler_id; + gchar *data; + gsize length; - loc_file = g_file_new_for_path(loc_path); - monitor = g_file_monitor_file(loc_file, G_FILE_MONITOR_SEND_MOVED, NULL, - NULL); - g_object_unref(loc_file); + DLEYNA_LOG_DEBUG("Enter"); - if (monitor != NULL) { - handler_id = g_signal_connect(monitor, "changed", - G_CALLBACK(prv_monitor_keyfile_cb), - settings); + data = g_key_file_to_data(settings->keyfile, &length , NULL); - settings->monitor = monitor; - settings->handler_id = handler_id; - } + DLEYNA_LOG_DEBUG_NL(); + DLEYNA_LOG_DEBUG("\n%s", data); + DLEYNA_LOG_DEBUG_NL(); + + (void) g_file_set_contents(settings->file_path, data, length, error); + + g_free(data); } gboolean dleyna_settings_is_never_quit(dleyna_settings_t *settings) @@ -522,65 +450,107 @@ gboolean dleyna_settings_is_never_quit(dleyna_settings_t *settings) return settings->never_quit; } -const gchar *dleyna_settings_connector_name(dleyna_settings_t *settings) +void dleyna_settings_set_never_quit(dleyna_settings_t *settings, + gboolean never_quit, + GError **error) { - return settings->connector_name; -} + DLEYNA_LOG_DEBUG("Enter"); -void dleyna_settings_new(const gchar *server, dleyna_settings_t **settings) -{ - gchar *sys_path = NULL; - gchar *loc_path = NULL; - const gchar *server_name; + g_key_file_set_boolean(settings->keyfile, + DLEYNA_SETTINGS_GROUP_GENERAL, + DLEYNA_SETTINGS_KEY_NEVER_QUIT, + never_quit); - *settings = g_malloc0(sizeof(**settings)); + prv_save_settings_to_file(settings, error); - server_name = strrchr(server, '/'); - if (server_name) - server_name++; - else - server_name = server; - (*settings)->file_name = g_strdup_printf("%s%s", server_name, ".conf"); + if (*error == NULL) + settings->never_quit = never_quit; - prv_init_default(*settings); + DLEYNA_LOG_DEBUG("Exit"); +} - prv_get_keyfile_path((*settings)->file_name, &sys_path, &loc_path); +gboolean dleyna_settings_is_white_list_enabled(dleyna_settings_t *settings) +{ + return settings->netf_enabled; +} - if (loc_path) { - prv_check_local_keyfile(sys_path, loc_path); - prv_monitor_local_keyfile(*settings, loc_path); - } +void dleyna_settings_set_white_list_enabled(dleyna_settings_t *settings, + gboolean enabled, + GError **error) +{ + DLEYNA_LOG_DEBUG("Enter"); - if (sys_path || loc_path) - prv_keyfile_init(*settings, sys_path, loc_path); + g_key_file_set_boolean(settings->keyfile, + DLEYNA_SETTINGS_GROUP_NETF, + DLEYNA_SETTINGS_KEY_NETF_ENABLED, + enabled); - DLEYNA_SETTINGS_LOG_KEYS(sys_path, loc_path, *settings); + prv_save_settings_to_file(settings, error); - g_free(sys_path); - g_free(loc_path); + if (*error == NULL) + settings->netf_enabled = enabled; + + DLEYNA_LOG_DEBUG("Exit"); } -void dleyna_settings_delete(dleyna_settings_t *settings) +GVariant *dleyna_settings_white_list_entries(dleyna_settings_t *settings) { - if (settings->monitor) { - if (settings->handler_id) - g_signal_handler_disconnect(settings->monitor, - settings->handler_id); + return settings->netf_entries; +} - g_file_monitor_cancel(settings->monitor); - g_object_unref(settings->monitor); - } +static const gchar **prv_filter_null_str(const gchar **orig_strv, + gsize orig_len, + gsize *new_len) +{ + const gchar **strv = NULL; + gsize i; + gsize n = 0; - g_free(settings->connector_name); - g_free(settings->file_name); + if (orig_strv && orig_len) { + strv = g_new(const gchar *, orig_len + 1); - prv_keyfile_finalize(settings); + for (i = 0; i < orig_len; i++) { + if (*orig_strv[i]) + strv[n++] = orig_strv[i]; + } - g_free(settings); + strv[n] = NULL; + } + + *new_len = n; + + return strv; } -void dleyna_settings_init_white_list(dleyna_settings_t *settings) +void dleyna_settings_set_white_list_entries(dleyna_settings_t *settings, + GVariant *entries, + GError **error) { - dleyna_white_list_add_entries(settings->netf_entries, TRUE); - dleyna_white_list_enable(settings->netf_enabled, TRUE); + const gchar **list; + gsize length; + const gchar **list2; + gsize length2; + + DLEYNA_LOG_DEBUG("Enter"); + + list = g_variant_get_strv(entries, &length); + + list2 = prv_filter_null_str(list, length, &length2); + + g_key_file_set_string_list(settings->keyfile, + DLEYNA_SETTINGS_GROUP_NETF, + DLEYNA_SETTINGS_KEY_NETF_LIST, + list2, length2); + + prv_save_settings_to_file(settings, error); + + if (*error == NULL) { + g_variant_unref(settings->netf_entries); + settings->netf_entries = g_variant_ref(entries); + } + + g_free(list); + g_free(list2); + + DLEYNA_LOG_DEBUG("Exit"); } diff --git a/libdleyna/core/settings.h b/libdleyna/core/settings.h index b09456f..76d2198 100644 --- a/libdleyna/core/settings.h +++ b/libdleyna/core/settings.h @@ -31,10 +31,24 @@ void dleyna_settings_new(const gchar *server, dleyna_settings_t **settings); void dleyna_settings_delete(dleyna_settings_t *settings); -void dleyna_settings_init_white_list(dleyna_settings_t *settings); +const gchar *dleyna_settings_connector_name(dleyna_settings_t *settings); gboolean dleyna_settings_is_never_quit(dleyna_settings_t *settings); -const gchar *dleyna_settings_connector_name(dleyna_settings_t *settings); +void dleyna_settings_set_never_quit(dleyna_settings_t *settings, + gboolean never_quit, + GError **error); + +gboolean dleyna_settings_is_white_list_enabled(dleyna_settings_t *settings); + +void dleyna_settings_set_white_list_enabled(dleyna_settings_t *settings, + gboolean enabled, + GError **error); + +GVariant *dleyna_settings_white_list_entries(dleyna_settings_t *settings); + +void dleyna_settings_set_white_list_entries(dleyna_settings_t *settings, + GVariant *entries, + GError **error); #endif /* DLEYNA_SETTINGS_H__ */ diff --git a/libdleyna/core/white-list.c b/libdleyna/core/white-list.c index fa5d2d0..f1ea7b5 100644 --- a/libdleyna/core/white-list.c +++ b/libdleyna/core/white-list.c @@ -25,7 +25,9 @@ #include "white-list.h" #include "log.h" -static dleyna_white_list_t g_wl_cb; +struct dleyna_white_list_t_ { + GUPnPWhiteList *gupnp_wl; +}; #if DLEYNA_LOG_LEVEL & DLEYNA_LOG_LEVEL_DEBUG static void prv_dump_wl_entries(GUPnPWhiteList *wl) @@ -50,76 +52,87 @@ static void prv_dump_wl_entries(GUPnPWhiteList *wl) } #endif -void dleyna_white_list_enable(gboolean enabled, gboolean notify) +dleyna_white_list_t *dleyna_white_list_new(GUPnPWhiteList *gupnp_wl) { - if (g_wl_cb.wl != NULL) { - gupnp_white_list_set_enabled(g_wl_cb.wl, enabled); + dleyna_white_list_t *wl; - DLEYNA_LOG_DEBUG("White List enabled: %d", enabled); + if (gupnp_wl != NULL) { + wl = g_new0(dleyna_white_list_t, 1); - if (notify && (g_wl_cb.cb_enabled != NULL)) - g_wl_cb.cb_enabled(g_wl_cb.user_data); + wl->gupnp_wl = gupnp_wl; + } else { + wl = NULL; + DLEYNA_LOG_DEBUG("Parameter must not be NULL"); } + + + return wl; } -void dleyna_white_list_add_entries(GVariant *entries, gboolean notify) +void dleyna_white_list_delete(dleyna_white_list_t *wl) +{ + g_free(wl); +} + +void dleyna_white_list_enable(dleyna_white_list_t *wl, + gboolean enabled) +{ + if (wl->gupnp_wl != NULL) { + gupnp_white_list_set_enabled(wl->gupnp_wl, enabled); + + DLEYNA_LOG_DEBUG("White List enabled: %d", enabled); + } +} + +void dleyna_white_list_add_entries(dleyna_white_list_t *wl, + GVariant *entries) { GVariantIter viter; gchar *entry; - if ((entries != NULL) && (g_wl_cb.wl != NULL)) { + DLEYNA_LOG_DEBUG("Enter"); + + if ((entries != NULL) && (wl->gupnp_wl != NULL)) { (void) g_variant_iter_init(&viter, entries); while (g_variant_iter_next(&viter, "&s", &entry)) - (void) gupnp_white_list_add_entry(g_wl_cb.wl, entry); + (void) gupnp_white_list_add_entry(wl->gupnp_wl, entry); #if DLEYNA_LOG_LEVEL & DLEYNA_LOG_LEVEL_DEBUG - prv_dump_wl_entries(g_wl_cb.wl); + prv_dump_wl_entries(wl->gupnp_wl); #endif - - if (notify && (g_wl_cb.cb_entries != NULL)) - g_wl_cb.cb_entries(g_wl_cb.user_data); } + + DLEYNA_LOG_DEBUG("Exit"); } -void dleyna_white_list_remove_entries(GVariant *entries, gboolean notify) +void dleyna_white_list_remove_entries(dleyna_white_list_t *wl, + GVariant *entries) { GVariantIter viter; gchar *entry; - if ((entries != NULL) && (g_wl_cb.wl != NULL)) { + if ((entries != NULL) && (wl->gupnp_wl != NULL)) { (void) g_variant_iter_init(&viter, entries); while (g_variant_iter_next(&viter, "&s", &entry)) - (void) gupnp_white_list_remove_entry(g_wl_cb.wl, entry); + (void) gupnp_white_list_remove_entry(wl->gupnp_wl, + entry); #if DLEYNA_LOG_LEVEL & DLEYNA_LOG_LEVEL_DEBUG - prv_dump_wl_entries(g_wl_cb.wl); + prv_dump_wl_entries(wl->gupnp_wl); #endif - - if (notify && (g_wl_cb.cb_entries != NULL)) - g_wl_cb.cb_entries(g_wl_cb.user_data); } } -void dleyna_white_list_clear(gboolean notify) +void dleyna_white_list_clear(dleyna_white_list_t *wl) { - if (g_wl_cb.wl != NULL) { - gupnp_white_list_clear(g_wl_cb.wl); + if (wl->gupnp_wl != NULL) { + DLEYNA_LOG_DEBUG("Clear white list"); + gupnp_white_list_clear(wl->gupnp_wl); #if DLEYNA_LOG_LEVEL & DLEYNA_LOG_LEVEL_DEBUG - prv_dump_wl_entries(g_wl_cb.wl); + prv_dump_wl_entries(wl->gupnp_wl); #endif - - if (notify && (g_wl_cb.cb_entries != NULL)) - g_wl_cb.cb_entries(g_wl_cb.user_data); } } - -void dleyna_white_list_set_info(dleyna_white_list_t *data) -{ - if (data != NULL) - memcpy(&g_wl_cb, data, sizeof(dleyna_white_list_t)); - else - memset(&g_wl_cb, 0, sizeof(dleyna_white_list_t)); -} diff --git a/libdleyna/core/white-list.h b/libdleyna/core/white-list.h index a0e760e..354b407 100644 --- a/libdleyna/core/white-list.h +++ b/libdleyna/core/white-list.h @@ -26,25 +26,19 @@ #include #include -typedef void (*dleyna_white_list_notify_t)(gpointer user_data); - typedef struct dleyna_white_list_t_ dleyna_white_list_t; -struct dleyna_white_list_t_ { - GUPnPWhiteList *wl; - dleyna_white_list_notify_t cb_enabled; - dleyna_white_list_notify_t cb_entries; - gpointer user_data; -}; +dleyna_white_list_t *dleyna_white_list_new(GUPnPWhiteList *gupnp_wl); -void dleyna_white_list_enable(gboolean enabled, gboolean notify); +void dleyna_white_list_delete(dleyna_white_list_t *wl); -void dleyna_white_list_add_entries(GVariant *entries, gboolean notify); +void dleyna_white_list_enable(dleyna_white_list_t *wl, gboolean enabled); -void dleyna_white_list_remove_entries(GVariant *entries, gboolean notify); +void dleyna_white_list_add_entries(dleyna_white_list_t *wl, GVariant *entries); -void dleyna_white_list_clear(gboolean notify); +void dleyna_white_list_remove_entries(dleyna_white_list_t *wl, + GVariant *entries); -void dleyna_white_list_set_info(dleyna_white_list_t *data); +void dleyna_white_list_clear(dleyna_white_list_t *wl); #endif /* DLEYNA_WHITE_LIST_H__ */ -- cgit v1.2.1