[gupnp] Use GUPnPWhiteList in GUPnPContextManager
- From: Jens Georg <jensgeorg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gupnp] Use GUPnPWhiteList in GUPnPContextManager
- Date: Fri, 16 Aug 2013 11:15:33 +0000 (UTC)
commit 37554c2b9279dc13ffaf2224fae993e82094a8f2
Author: Ludovic Ferrandis <ludovic ferrandis intel com>
Date: Wed Aug 7 15:31:59 2013 +0200
Use GUPnPWhiteList in GUPnPContextManager
GUPnPContextManager is now using GUPnPWhiteList to filter networks
Add test program
https://bugzilla.gnome.org/show_bug.cgi?id=705712
libgupnp/gupnp-context-manager.c | 233 ++++++++++++++++++++++++++++++++--
libgupnp/gupnp-context-manager.h | 5 +
tests/Makefile.am | 8 +-
tests/test-white-list.c | 262 ++++++++++++++++++++++++++++++++++++++
4 files changed, 495 insertions(+), 13 deletions(-)
---
diff --git a/libgupnp/gupnp-context-manager.c b/libgupnp/gupnp-context-manager.c
index 4bf3cee..4e0a84a 100644
--- a/libgupnp/gupnp-context-manager.c
+++ b/libgupnp/gupnp-context-manager.c
@@ -1,9 +1,11 @@
/*
* Copyright (C) 2009 Nokia Corporation.
* Copyright (C) 2006, 2007, 2008 OpenedHand Ltd.
+ * Copyright (C) 2013 Intel Corporation.
*
* Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
* Jorn Baayen <jorn openedhand com>
+ * Ludovic Ferrandis <ludovic ferrandis intel com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -55,12 +57,16 @@ struct _GUPnPContextManagerPrivate {
GUPnPContextManager *impl;
GList *objects; /* control points and root devices */
+ GList *blacklisted; /* Blacklisted Context */
+
+ GUPnPWhiteList *white_list;
};
enum {
PROP_0,
PROP_MAIN_CONTEXT,
PROP_PORT,
+ PROP_WHITE_LIST
};
enum {
@@ -72,11 +78,40 @@ enum {
static guint signals[SIGNAL_LAST];
static void
+on_context_available (GUPnPContextManager *manager,
+ GUPnPContext *context,
+ G_GNUC_UNUSED gpointer *user_data)
+{
+ GUPnPWhiteList *white_list;
+
+ white_list = manager->priv->white_list;
+
+ /* Try to catch the notification, only if the white list
+ * is enabled, not empty and the context doesn't match */
+ if (!gupnp_white_list_is_empty (white_list) &&
+ gupnp_white_list_is_enabled (white_list) &&
+ !gupnp_white_list_check_context (white_list, context)) {
+ /* If the conext doesn't match, block the notification
+ * and disable the context */
+ g_signal_stop_emission_by_name (manager, "context-available");
+
+ /* Make sure we don't send anything on now blocked network */
+ g_object_set (context, "active", FALSE, NULL);
+
+ /* Save it in case we need to re-enable it */
+ manager->priv->blacklisted = g_list_prepend (
+ manager->priv->blacklisted,
+ g_object_ref (context));
+ }
+}
+
+static void
on_context_unavailable (GUPnPContextManager *manager,
GUPnPContext *context,
G_GNUC_UNUSED gpointer *user_data)
{
GList *l;
+ GList *black;
/* Make sure we don't send anything on now unavailable network */
g_object_set (context, "active", FALSE, NULL);
@@ -113,6 +148,119 @@ on_context_unavailable (GUPnPContextManager *manager,
l = l->next;
}
}
+
+ black = g_list_find (manager->priv->blacklisted, context);
+
+ if (black != NULL) {
+ g_signal_stop_emission_by_name (manager, "context-unavailable");
+
+ g_object_unref (black->data);
+ manager->priv->blacklisted =
+ g_list_delete_link (manager->priv->blacklisted, black);
+ }
+}
+
+static void
+gupnp_context_manager_filter_context (GUPnPWhiteList *white_list,
+ GUPnPContextManager *manager,
+ gboolean check)
+{
+ GList *next;
+ GList *obj;
+ GList *blk;
+ gboolean match;
+ GUPnPContext *context;
+ GSSDPResourceBrowser *browser;
+
+ obj = manager->priv->objects;
+ blk = manager->priv->blacklisted;
+
+ while (obj != NULL) {
+ if (!GUPNP_IS_CONTROL_POINT (obj->data))
+ continue;
+
+ /* If the white list is empty, treat it as disabled */
+ if (check) {
+ /* Filter out context */
+ context = gupnp_control_point_get_context (obj->data);
+ match = gupnp_white_list_check_context (white_list,
+ context);
+ } else {
+ /* Re-activate all context, if needed */
+ match = TRUE;
+ }
+
+ browser = GSSDP_RESOURCE_BROWSER (obj->data);
+ gssdp_resource_browser_set_active (browser, match);
+
+ if (match)
+ (void) gssdp_resource_browser_rescan (browser);
+
+ obj = obj->next;
+ }
+
+ while (blk != NULL) {
+ /* If the white list is empty, treat it as disabled */
+ if (check)
+ /* Filter out context */
+ match = gupnp_white_list_check_context (white_list,
+ blk->data);
+ else
+ /* Re-activate all context, if needed */
+ match = TRUE;
+
+ if (!match) {
+ blk = blk->next;
+ continue;
+ }
+
+ next = blk->next;
+ g_object_set (blk->data, "active", TRUE, NULL);
+
+ g_signal_emit_by_name (manager, "context-available", blk->data);
+
+ g_object_unref (blk->data);
+ manager->priv->blacklisted = g_list_delete_link (
+ manager->priv->blacklisted,
+ blk);
+ blk = next;
+ }
+}
+
+static void
+on_white_list_change_cb (GUPnPWhiteList *white_list,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ GUPnPContextManager *manager = GUPNP_CONTEXT_MANAGER (user_data);
+ gboolean enabled;
+ gboolean is_empty;
+
+ enabled = gupnp_white_list_is_enabled (white_list);
+ is_empty = gupnp_white_list_is_empty (white_list);
+
+ if (enabled)
+ gupnp_context_manager_filter_context (white_list,
+ manager,
+ !is_empty);
+}
+
+static void
+on_white_list_enabled_cb (GUPnPWhiteList *white_list,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ GUPnPContextManager *manager = GUPNP_CONTEXT_MANAGER (user_data);
+ gboolean enabled;
+ gboolean is_empty;
+
+ enabled = gupnp_white_list_is_enabled (white_list);
+ is_empty = gupnp_white_list_is_empty (white_list);
+
+ if (!is_empty)
+ gupnp_context_manager_filter_context (white_list,
+ manager,
+ enabled);
}
static void
@@ -122,6 +270,14 @@ gupnp_context_manager_init (GUPnPContextManager *manager)
G_TYPE_INSTANCE_GET_PRIVATE (manager,
GUPNP_TYPE_CONTEXT_MANAGER,
GUPnPContextManagerPrivate);
+
+ manager->priv->white_list = gupnp_white_list_new ();
+
+ g_signal_connect_after (manager->priv->white_list, "notify::entries",
+ G_CALLBACK (on_white_list_change_cb), manager);
+
+ g_signal_connect_after (manager->priv->white_list, "notify::enabled",
+ G_CALLBACK (on_white_list_enabled_cb), manager);
}
static void
@@ -174,6 +330,9 @@ gupnp_context_manager_get_property (GObject *object,
g_value_set_pointer (value,
g_main_context_get_thread_default ());
break;
+ case PROP_WHITE_LIST:
+ g_value_set_object (value, manager->priv->white_list);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -184,13 +343,29 @@ static void
gupnp_context_manager_dispose (GObject *object)
{
GUPnPContextManager *manager;
+ GUPnPWhiteList *wl;
GObjectClass *object_class;
manager = GUPNP_CONTEXT_MANAGER (object);
+ wl = manager->priv->white_list;
+
+ g_signal_handlers_disconnect_by_func (wl,
+ on_white_list_enabled_cb,
+ manager);
- g_list_foreach (manager->priv->objects, (GFunc) g_object_unref, NULL);
- g_list_free (manager->priv->objects);
+ g_signal_handlers_disconnect_by_func (wl,
+ on_white_list_change_cb,
+ NULL);
+
+ g_list_free_full (manager->priv->objects, g_object_unref);
manager->priv->objects = NULL;
+ g_list_free_full (manager->priv->blacklisted, g_object_unref);
+ manager->priv->blacklisted = NULL;
+
+ if (wl) {
+ g_object_unref (wl);
+ manager->priv->white_list = NULL;
+ }
/* Call super */
object_class = G_OBJECT_CLASS (gupnp_context_manager_parent_class);
@@ -250,7 +425,24 @@ gupnp_context_manager_class_init (GUPnPContextManagerClass *klass)
G_PARAM_STATIC_NICK |
G_PARAM_STATIC_BLURB));
- /**
+ /**
+ * GUPnPContextManager:white-list:
+ *
+ * The white list to use.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_WHITE_LIST,
+ g_param_spec_object ("white-list",
+ "White List",
+ "The white list to use",
+ GUPNP_TYPE_WHITE_LIST,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
* GUPnPContextManager::context-available:
* @context_manager: The #GUPnPContextManager that received the signal
* @context: The now available #GUPnPContext
@@ -259,15 +451,15 @@ gupnp_context_manager_class_init (GUPnPContextManagerClass *klass)
*
**/
signals[CONTEXT_AVAILABLE] =
- g_signal_new ("context-available",
- GUPNP_TYPE_CONTEXT_MANAGER,
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE,
- 1,
- GUPNP_TYPE_CONTEXT);
+ g_signal_new_class_handler ("context-available",
+ GUPNP_TYPE_CONTEXT_MANAGER,
+ G_SIGNAL_RUN_FIRST,
+ G_CALLBACK (on_context_available),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE,
+ 1,
+ GUPNP_TYPE_CONTEXT);
/**
* GUPnPContextManager::context-unavailable:
@@ -467,3 +659,20 @@ gupnp_context_manager_get_port (GUPnPContextManager *manager)
return manager->priv->port;
}
+
+/**
+ * gupnp_context_manager_get_white_list:
+ * @manager: A #GUPnPContextManager
+ *
+ * Get the #GUPnPWhiteList associated with @manager.
+ *
+ * Returns: (transfer none): The #GUPnPWhiteList asssociated with this
+ * context manager.
+ */
+GUPnPWhiteList *
+gupnp_context_manager_get_white_list (GUPnPContextManager *manager)
+{
+ g_return_val_if_fail (GUPNP_IS_CONTEXT_MANAGER (manager), NULL);
+
+ return manager->priv->white_list;
+}
diff --git a/libgupnp/gupnp-context-manager.h b/libgupnp/gupnp-context-manager.h
index 1e04b4c..6124ea9 100644
--- a/libgupnp/gupnp-context-manager.h
+++ b/libgupnp/gupnp-context-manager.h
@@ -26,6 +26,7 @@
#include <glib.h>
#include "gupnp.h"
+#include "gupnp-white-list.h"
G_BEGIN_DECLS
@@ -105,6 +106,10 @@ gupnp_context_manager_manage_root_device
guint
gupnp_context_manager_get_port (GUPnPContextManager *manager);
+
+GUPnPWhiteList *
+gupnp_context_manager_get_white_list (GUPnPContextManager *manager);
+
G_END_DECLS
#endif /* __GUPNP_CONTEXT_MANAGER_H__ */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 4c70f1a..8209270 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -5,7 +5,8 @@ AM_CFLAGS = $(LIBGUPNP_CFLAGS) $(GTHREAD_CFLAGS) -I$(top_srcdir)
noinst_PROGRAMS = test-browsing \
test-proxy \
test-server \
- test-introspection
+ test-introspection \
+ test-white-list
test_browsing_SOURCES = test-browsing.c
test_browsing_LDADD = $(top_builddir)/libgupnp/libgupnp-1.0.la \
@@ -28,6 +29,11 @@ test_server_LDADD = $(top_builddir)/libgupnp/libgupnp-1.0.la \
$(LIBGUPNP_LIBS)
test_server_LDFLAGS = -export-dynamic
+test_white_list_SOURCES = test-white-list.c
+test_white_list_LDADD = $(top_builddir)/libgupnp/libgupnp-1.0.la \
+ $(GTHREAD_LIBS) \
+ $(LIBGUPNP_LIBS)
+
CLEANFILES = $(BUILT_SOURCES)
DISTCLEANFILES = $(BUILT_SOURCES)
MAINTAINERCLEANFILES = Makefile.in $(BUILT_SOURCES)
diff --git a/tests/test-white-list.c b/tests/test-white-list.c
new file mode 100644
index 0000000..ed04d48
--- /dev/null
+++ b/tests/test-white-list.c
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2013 Intel Corporation.
+ *
+ * Author: Ludovic Ferrandis <ludovic ferrandis intel com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <libgupnp/gupnp-control-point.h>
+#include <libgupnp/gupnp-context-manager.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include <signal.h>
+#include <glib.h>
+
+GMainLoop *main_loop;
+
+static void
+interrupt_signal_handler (G_GNUC_UNUSED int signum)
+{
+ g_main_loop_quit (main_loop);
+}
+
+static void
+device_proxy_available_cb (G_GNUC_UNUSED GUPnPControlPoint *cp,
+ GUPnPDeviceProxy *proxy)
+{
+ const char *type, *location;
+
+ type = gupnp_device_info_get_device_type (GUPNP_DEVICE_INFO (proxy));
+ location = gupnp_device_info_get_location (GUPNP_DEVICE_INFO (proxy));
+
+ g_print ("Device available:\n");
+ g_print ("\ttype: %s\n", type);
+ g_print ("\tlocation: %s\n", location);
+}
+
+static void
+device_proxy_unavailable_cb (G_GNUC_UNUSED GUPnPControlPoint *cp,
+ GUPnPDeviceProxy *proxy)
+{
+ const char *type, *location;
+
+ type = gupnp_device_info_get_device_type (GUPNP_DEVICE_INFO (proxy));
+ location = gupnp_device_info_get_location (GUPNP_DEVICE_INFO (proxy));
+
+ g_print ("Device unavailable:\n");
+ g_print ("\ttype: %s\n", type);
+ g_print ("\tlocation: %s\n", location);
+}
+
+static void
+service_proxy_available_cb (G_GNUC_UNUSED GUPnPControlPoint *cp,
+ GUPnPServiceProxy *proxy)
+{
+ const char *type, *location;
+
+ type = gupnp_service_info_get_service_type (GUPNP_SERVICE_INFO (proxy));
+ location = gupnp_service_info_get_location (GUPNP_SERVICE_INFO (proxy));
+
+ g_print ("Service available:\n");
+ g_print ("\ttype: %s\n", type);
+ g_print ("\tlocation: %s\n", location);
+}
+
+static void
+service_proxy_unavailable_cb (G_GNUC_UNUSED GUPnPControlPoint *cp,
+ GUPnPServiceProxy *proxy)
+{
+ const char *type, *location;
+
+ type = gupnp_service_info_get_service_type (GUPNP_SERVICE_INFO (proxy));
+ location = gupnp_service_info_get_location (GUPNP_SERVICE_INFO (proxy));
+
+ g_print ("Service unavailable:\n");
+ g_print ("\ttype: %s\n", type);
+ g_print ("\tlocation: %s\n", location);
+}
+
+static void
+context_available_cb(GUPnPContextManager *context_manager,
+ GUPnPContext *context,
+ gpointer user_data)
+{
+ GUPnPControlPoint *cp;
+ GSSDPClient *client = GSSDP_CLIENT(context);
+
+ g_print ("Context Available:\n");
+ g_print ("\tServer ID: %s\n", gssdp_client_get_server_id (client));
+ g_print ("\tInterface: %s\n", gssdp_client_get_interface (client));
+ g_print ("\tHost IP : %s\n", gssdp_client_get_host_ip (client));
+ g_print ("\tNetwork : %s\n", gssdp_client_get_network (client));
+ g_print ("\tActive : %s\n", gssdp_client_get_active (client)? "TRUE" : "FALSE");
+
+
+ /* We're interested in everything */
+ cp = gupnp_control_point_new (context, "ssdp:all");
+
+ g_signal_connect (cp,
+ "device-proxy-available",
+ G_CALLBACK (device_proxy_available_cb),
+ NULL);
+ g_signal_connect (cp,
+ "device-proxy-unavailable",
+ G_CALLBACK (device_proxy_unavailable_cb),
+ NULL);
+ g_signal_connect (cp,
+ "service-proxy-available",
+ G_CALLBACK (service_proxy_available_cb),
+ NULL);
+ g_signal_connect (cp,
+ "service-proxy-unavailable",
+ G_CALLBACK (service_proxy_unavailable_cb),
+ NULL);
+
+ gssdp_resource_browser_set_active (GSSDP_RESOURCE_BROWSER (cp), TRUE);
+ gupnp_context_manager_manage_control_point(context_manager, cp);
+ g_object_unref(cp);
+}
+
+static void
+context_unavailable_cb(GUPnPContextManager *context_manager,
+ GUPnPContext *context,
+ gpointer user_data)
+{
+ GSSDPClient *client = GSSDP_CLIENT(context);
+
+ g_print ("Context Unavailable:\n");
+ g_print ("\tServer ID: %s\n", gssdp_client_get_server_id (client));
+ g_print ("\tInterface: %s\n", gssdp_client_get_interface (client));
+ g_print ("\tHost IP : %s\n", gssdp_client_get_host_ip (client));
+ g_print ("\tNetwork : %s\n", gssdp_client_get_network (client));
+ g_print ("\tActive : %s\n", gssdp_client_get_active (client)? "TRUE" : "FALSE");
+}
+
+static gboolean
+change_white_list(gpointer user_data)
+{
+ GUPnPContextManager *context_manager = user_data;
+ GUPnPWhiteList *white_list;
+ static int tomato = 0;
+
+ g_print ("\nChange White List:\n");
+ g_print ("\t Action number %d:\n", tomato);
+
+ white_list = gupnp_context_manager_get_white_list(context_manager);
+
+ switch (tomato) {
+ case 0:
+ g_print ("\t Add Entry eth0\n\n");
+ gupnp_white_list_add_entry(white_list, "eth0");
+ break;
+ case 1:
+ g_print ("\t Enable WL\n\n");
+ gupnp_white_list_enable(white_list, TRUE);
+ break;
+ case 2:
+ g_print ("\t Add Entry 127.0.0.1\n\n");
+ gupnp_white_list_add_entry(white_list, "127.0.0.1");
+ break;
+ case 3:
+ g_print ("\t Clear all entries\n\n");
+ gupnp_white_list_clear(white_list);
+ break;
+ case 4:
+ g_print ("\t Add Entry wlan2\n\n");
+ gupnp_white_list_add_entry(white_list, "wlan2");
+ break;
+ case 5:
+ g_print ("\t Disable WL\n\n");
+ gupnp_white_list_enable(white_list, FALSE);
+ break;
+ case 6:
+ g_print ("\t Enable WL\n\n");
+ gupnp_white_list_enable(white_list, TRUE);
+ break;
+ case 7:
+ g_print ("\t Connect to wlan0\n\n");
+ g_timeout_add_seconds (35, change_white_list, context_manager);
+ break;
+ case 8:
+ g_print ("\t Add Entry wlan0\n\n");
+ gupnp_white_list_add_entry(white_list, "wlan0");
+ break;
+ //~ case 8:
+ //~ g_print ("\t Enable WL\n");
+ //~ gupnp_white_list_enable(white_list, FALSE);
+ //~ break;
+ default:
+ break;
+ }
+
+ tomato++;
+
+ return (tomato < 9) && (tomato != 8);
+}
+
+int
+main (G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv)
+{
+ GError *error;
+ GUPnPContextManager *cm;
+ guint id;
+#ifndef G_OS_WIN32
+ struct sigaction sig_action;
+#endif /* G_OS_WIN32 */
+
+#if !GLIB_CHECK_VERSION(2,35,0)
+ g_type_init ();
+#endif
+ setlocale (LC_ALL, "");
+
+ error = NULL;
+
+ cm = gupnp_context_manager_create(0);
+
+ g_signal_connect(cm,
+ "context-available",
+ G_CALLBACK(context_available_cb),
+ NULL);
+
+ g_signal_connect(cm,
+ "context-unavailable",
+ G_CALLBACK(context_unavailable_cb),
+ NULL);
+
+ main_loop = g_main_loop_new (NULL, FALSE);
+
+ id = g_timeout_add_seconds (5, change_white_list, cm);
+
+#ifndef G_OS_WIN32
+ /* Hook the handler for SIGTERM */
+ memset (&sig_action, 0, sizeof (sig_action));
+ sig_action.sa_handler = interrupt_signal_handler;
+ sigaction (SIGINT, &sig_action, NULL);
+#else
+ signal(SIGINT, interrupt_signal_handler);
+#endif /* G_OS_WIN32 */
+
+ g_main_loop_run (main_loop);
+ g_main_loop_unref (main_loop);
+
+ g_source_remove (id);
+
+ g_object_unref (cm);
+
+ return EXIT_SUCCESS;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]