[gupnp/wip/acl] wip: Add device/service information to ACL



commit 5b06231d7cd0ce158c631dbaeb2b1ec82f465993
Author: Jens Georg <mail jensge org>
Date:   Sun Feb 23 16:33:01 2014 +0100

    wip: Add device/service information to ACL
    
    Signed-off-by: Jens Georg <mail jensge org>

 libgupnp/gupnp-acl-private.h     |   77 +++++++++++++++++++++++++
 libgupnp/gupnp-acl.c             |   93 ++++++++++++++++++++++++++++++-
 libgupnp/gupnp-acl.h             |   24 +++++++-
 libgupnp/gupnp-context-private.h |    7 ++
 libgupnp/gupnp-context.c         |  114 ++++++++++---------------------------
 libgupnp/gupnp-service.c         |   15 +++--
 6 files changed, 234 insertions(+), 96 deletions(-)
---
diff --git a/libgupnp/gupnp-acl-private.h b/libgupnp/gupnp-acl-private.h
new file mode 100644
index 0000000..9d8f992
--- /dev/null
+++ b/libgupnp/gupnp-acl-private.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2013 Jens Georg <mail jensge org>
+ *
+ * Author: Jens Georg <mail jensge org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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.
+ */
+
+#ifndef __GUPNP_ACL_PRIVATE_H__
+#define __GUPNP_ACL_PRIVATE_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <libsoup/soup-session.h>
+
+#include "gupnp-acl.h"
+#include "gupnp-context.h"
+
+G_BEGIN_DECLS
+
+typedef struct _AclServerHandler
+{
+        GUPnPService *service;
+        GUPnPContext *context;
+        SoupServerCallback callback;
+        gpointer user_data;
+        GDestroyNotify notify;
+} AclServerHandler;
+
+typedef struct _AsyncAclHandler
+{
+        SoupServer *server;
+        SoupMessage *message;
+        char *path;
+        GHashTable *query;
+        SoupClientContext *client;
+        AclServerHandler *handler;
+} AsyncAclHandler;
+
+G_GNUC_INTERNAL AclServerHandler *
+acl_server_handler_new (GUPnPService *service,
+                        GUPnPContext *context,
+                        SoupServerCallback callback,
+                        gpointer user_data,
+                        GDestroyNotify notify);
+
+G_GNUC_INTERNAL void
+acl_server_handler_free (AclServerHandler *handler);
+
+G_GNUC_INTERNAL AsyncAclHandler *
+async_acl_handler_new (SoupServer *server,
+                       SoupMessage *message,
+                       const char *path,
+                       GHashTable *query,
+                       SoupClientContext *client,
+                       AclServerHandler *handler);
+
+G_GNUC_INTERNAL void
+async_acl_handler_free (AsyncAclHandler *handler);
+
+
+G_END_DECLS
+
+#endif
diff --git a/libgupnp/gupnp-acl.c b/libgupnp/gupnp-acl.c
index 4a5abbf..8118965 100644
--- a/libgupnp/gupnp-acl.c
+++ b/libgupnp/gupnp-acl.c
@@ -20,6 +20,7 @@
  */
 
 #include "gupnp-acl.h"
+#include "gupnp-acl-private.h"
 
 G_DEFINE_INTERFACE(GUPnPAcl, gupnp_acl, G_TYPE_OBJECT)
 
@@ -31,6 +32,11 @@ gupnp_acl_default_init (GUPnPAclInterface *klass)
 /**
  * gupnp_acl_is_allowed:
  * @self: an instance of #GUPnPAcl
+ * @device: (allow-none): The #GUPnPDevice associated with @path or %NULL if
+ * unknown.
+ * @service: (allow-none): The #GUPnPService associated with @path or %NULL if
+ * unknown.
+ * @path: The path being served.
  * @address: IP address of the peer.
  * @returns: %TRUE if the peer is allowed, %FALSE otherwise
  *
@@ -39,16 +45,29 @@ gupnp_acl_default_init (GUPnPAclInterface *klass)
  * Since: 0.21.0
  */
 gboolean
-gupnp_acl_is_allowed (GUPnPAcl *self, const char *address)
+gupnp_acl_is_allowed (GUPnPAcl     *self,
+                      GUPnPDevice  *device,
+                      GUPnPService *service,
+                      const char   *path,
+                      const char   *address)
 {
         g_return_val_if_fail (GUPNP_IS_ACL (self), FALSE);
 
-        return GUPNP_ACL_GET_INTERFACE (self)->is_allowed (self, address);
+        return GUPNP_ACL_GET_INTERFACE (self)->is_allowed (self,
+                                                           device,
+                                                           service,
+                                                           path,
+                                                           address);
 }
 
 /**
  * gupnp_acl_is_allowed_async:
  * @self: a #GUPnPAcl
+ * @device: (allow-none): The #GUPnPDevice associated with @path or %NULL if
+ * unknown.
+ * @service: (allow-none): The #GUPnPService associated with @path or %NULL if
+ * unknown.
+ * @path: The path being served.
  * @address: IP address of the peer
  * @cancellable: (allow-none): A #GCancellable which can be used to cancel the
  * operation.
@@ -67,6 +86,9 @@ gupnp_acl_is_allowed (GUPnPAcl *self, const char *address)
  */
 void
 gupnp_acl_is_allowed_async (GUPnPAcl           *self,
+                            GUPnPDevice        *device,
+                            GUPnPService       *service,
+                            const char         *path,
                             const char         *address,
                             GCancellable       *cancellable,
                             GAsyncReadyCallback callback,
@@ -75,6 +97,9 @@ gupnp_acl_is_allowed_async (GUPnPAcl           *self,
         g_return_if_fail (GUPNP_IS_ACL (self));
 
         GUPNP_ACL_GET_INTERFACE (self)->is_allowed_async (self,
+                                                          device,
+                                                          service,
+                                                          path,
                                                           address,
                                                           cancellable,
                                                           callback,
@@ -120,3 +145,67 @@ gupnp_acl_can_sync (GUPnPAcl *self)
 
         return GUPNP_ACL_GET_INTERFACE (self)->can_sync (self);
 }
+
+AclServerHandler *
+acl_server_handler_new (GUPnPService *service,
+                        GUPnPContext *context,
+                        SoupServerCallback callback,
+                        gpointer user_data,
+                        GDestroyNotify notify)
+{
+        AclServerHandler *handler = g_new0 (AclServerHandler, 1);
+
+        handler->service = service ? g_object_ref (service) : NULL;
+        handler->context = g_object_ref (context);
+        handler->callback = callback;
+        handler->user_data = user_data;
+        handler->notify = notify;
+
+        return handler;
+}
+
+void
+acl_server_handler_free (AclServerHandler *handler)
+{
+        g_clear_object (&handler->service);
+        g_clear_object (&handler->context);
+
+        if (handler->notify != NULL)
+                handler->notify (handler->user_data);
+
+        g_free (handler);
+}
+
+AsyncAclHandler *
+async_acl_handler_new (SoupServer *server,
+                       SoupMessage *message,
+                       const char *path,
+                       GHashTable *query,
+                       SoupClientContext *client,
+                       AclServerHandler *handler)
+{
+        AsyncAclHandler *data = g_slice_new0 (AsyncAclHandler);
+
+        data->server = g_object_ref (server);
+        data->message = g_object_ref (message);
+        data->path = g_strdup (path);
+        if (query != NULL)
+                data->query = g_hash_table_ref (query);
+        data->client = g_boxed_copy (SOUP_TYPE_CLIENT_CONTEXT, client);
+        data->handler = handler;
+
+        return data;
+}
+
+void
+async_acl_handler_free (AsyncAclHandler *handler)
+{
+        g_object_unref (handler->server);
+        g_object_unref (handler->message);
+        g_free (handler->path);
+        if (handler->query != NULL)
+                g_hash_table_unref (handler->query);
+        g_boxed_free (SOUP_TYPE_CLIENT_CONTEXT, handler->client);
+
+        g_slice_free (AsyncAclHandler, handler);
+}
diff --git a/libgupnp/gupnp-acl.h b/libgupnp/gupnp-acl.h
index 619b22d..7aef20c 100644
--- a/libgupnp/gupnp-acl.h
+++ b/libgupnp/gupnp-acl.h
@@ -49,13 +49,23 @@ gupnp_acl_get_type (void) G_GNUC_CONST;
 typedef struct _GUPnPAcl GUPnPAcl;
 typedef struct _GUPnPAclInterface GUPnPAclInterface;
 
+/* Forward declarations to avoid recursive includes */
+typedef struct _GUPnPDevice GUPnPDevice;
+typedef struct _GUPnPService GUPnPService;
+
 struct _GUPnPAclInterface {
     GTypeInterface parent;
 
-    gboolean (*is_allowed) (GUPnPAcl   *self,
-                            const char *address);
+    gboolean (*is_allowed) (GUPnPAcl     *self,
+                            GUPnPDevice  *device,
+                            GUPnPService *service,
+                            const char   *path,
+                            const char   *address);
 
     void     (*is_allowed_async) (GUPnPAcl           *self,
+                                  GUPnPDevice        *device,
+                                  GUPnPService       *service,
+                                  const char         *path,
                                   const char         *address,
                                   GCancellable       *cancellable,
                                   GAsyncReadyCallback callback,
@@ -75,11 +85,17 @@ struct _GUPnPAclInterface {
 };
 
 gboolean
-gupnp_acl_is_allowed (GUPnPAcl   *self,
-                      const char *address);
+gupnp_acl_is_allowed (GUPnPAcl     *self,
+                      GUPnPDevice  *device,
+                      GUPnPService *service,
+                      const char   *path,
+                      const char   *address);
 
 void
 gupnp_acl_is_allowed_async (GUPnPAcl           *self,
+                            GUPnPDevice        *device,
+                            GUPnPService       *service,
+                            const char         *path,
                             const char         *address,
                             GCancellable       *cancellable,
                             GAsyncReadyCallback callback,
diff --git a/libgupnp/gupnp-context-private.h b/libgupnp/gupnp-context-private.h
index 18c4813..212d5e0 100644
--- a/libgupnp/gupnp-context-private.h
+++ b/libgupnp/gupnp-context-private.h
@@ -24,11 +24,18 @@
 
 #include <libsoup/soup.h>
 
+#include "gupnp-acl-private.h"
+
 G_BEGIN_DECLS
 
 G_GNUC_INTERNAL const char *
 _gupnp_context_get_server_url (GUPnPContext *context);
 
+G_GNUC_INTERNAL void
+_gupnp_context_add_server_handler_with_data (GUPnPContext *context,
+                                             const char *path,
+                                             AclServerHandler *data);
+
 G_END_DECLS
 
 #endif /* __GUPNP_CONTEXT_PRIVATE_H__ */
diff --git a/libgupnp/gupnp-context.c b/libgupnp/gupnp-context.c
index c906175..6aca2eb 100644
--- a/libgupnp/gupnp-context.c
+++ b/libgupnp/gupnp-context.c
@@ -50,6 +50,7 @@
 #include <glib/gstdio.h>
 
 #include "gupnp-acl.h"
+#include "gupnp-acl-private.h"
 #include "gupnp-context.h"
 #include "gupnp-context-private.h"
 #include "gupnp-error.h"
@@ -59,41 +60,6 @@
 
 #define GUPNP_CONTEXT_DEFAULT_LANGUAGE "en"
 
-typedef struct _GUPnPContextAclServerHandler
-{
-        GUPnPContext *context;
-        SoupServerCallback callback;
-        gpointer user_data;
-        GDestroyNotify notify;
-} GUPnPContextAclServerHandler;
-
-static GUPnPContextAclServerHandler *
-gupnp_acl_server_handler_new (GUPnPContext *context,
-                              SoupServerCallback callback,
-                              gpointer user_data,
-                              GDestroyNotify notify)
-{
-        GUPnPContextAclServerHandler *handler = g_new0 (GUPnPContextAclServerHandler, 1);
-
-        handler->context = g_object_ref (context);
-        handler->callback = callback;
-        handler->user_data = user_data;
-        handler->notify = notify;
-
-        return handler;
-}
-
-static void
-gupnp_acl_server_handler_free (GUPnPContextAclServerHandler *handler)
-{
-        g_clear_object (&handler->context);
-
-        if (handler->notify != NULL)
-                handler->notify (handler->user_data);
-
-        g_free (handler);
-}
-
 static void
 gupnp_acl_server_handler (SoupServer *server,
                           SoupMessage *msg,
@@ -1384,50 +1350,6 @@ gupnp_context_set_acl (GUPnPContext *context, GUPnPAcl *acl)
         g_object_notify (G_OBJECT (context), "acl");
 }
 
-typedef struct _AsyncAclHandler
-{
-        SoupServer *server;
-        SoupMessage *message;
-        char *path;
-        GHashTable *query;
-        SoupClientContext *client;
-        GUPnPContextAclServerHandler *handler;
-} AsyncAclHandler;
-
-static AsyncAclHandler *
-async_acl_handler_new (SoupServer *server,
-                       SoupMessage *message,
-                       const char *path,
-                       GHashTable *query,
-                       SoupClientContext *client,
-                       GUPnPContextAclServerHandler *handler)
-{
-        AsyncAclHandler *data = g_slice_new0 (AsyncAclHandler);
-
-        data->server = g_object_ref (server);
-        data->message = g_object_ref (message);
-        data->path = g_strdup (path);
-        if (query != NULL)
-                data->query = g_hash_table_ref (query);
-        data->client = g_boxed_copy (SOUP_TYPE_CLIENT_CONTEXT, client);
-        data->handler = handler;
-
-        return data;
-}
-
-void
-async_acl_handler_free (AsyncAclHandler *handler)
-{
-        g_object_unref (handler->server);
-        g_object_unref (handler->message);
-        g_free (handler->path);
-        if (handler->query != NULL)
-                g_hash_table_unref (handler->query);
-        g_boxed_free (SOUP_TYPE_CLIENT_CONTEXT, handler->client);
-
-        g_slice_free (AsyncAclHandler, handler);
-}
-
 static void
 gupnp_acl_async_callback (GUPnPAcl *acl,
                           GAsyncResult *res,
@@ -1459,10 +1381,19 @@ gupnp_acl_server_handler (SoupServer *server,
                           SoupClientContext *client,
                           gpointer user_data)
 {
-        GUPnPContextAclServerHandler *handler = (GUPnPContextAclServerHandler *) user_data;
+        AclServerHandler *handler = (AclServerHandler *) user_data;
+        GUPnPDevice *device = NULL;
+        if (handler->service) {
+                g_object_get (handler->service,
+                              "root-device", &device,
+                              NULL);
+        }
 
         if (gupnp_acl_can_sync (handler->context->priv->acl)) {
                 if (!gupnp_acl_is_allowed (handler->context->priv->acl,
+                                           device,
+                                           handler->service,
+                                           path,
                                            soup_client_context_get_host (client))) {
                         soup_message_set_status (msg, SOUP_STATUS_FORBIDDEN);
 
@@ -1475,6 +1406,9 @@ gupnp_acl_server_handler (SoupServer *server,
 
                 soup_server_pause_message (server, msg);
                 gupnp_acl_is_allowed_async (handler->context->priv->acl,
+                                            device,
+                                            handler->service,
+                                            path,
                                             soup_client_context_get_host (client),
                                             NULL,
                                             (GAsyncReadyCallback) gupnp_acl_async_callback,
@@ -1511,13 +1445,13 @@ gupnp_context_add_server_handler (GUPnPContext *context,
         g_return_if_fail (GUPNP_IS_CONTEXT (context));
 
         if (use_acl) {
-                GUPnPContextAclServerHandler *handler;
-                handler = gupnp_acl_server_handler_new (context, callback, user_data, destroy);
+                AclServerHandler *handler;
+                handler = acl_server_handler_new (NULL, context, callback, user_data, destroy);
                 soup_server_add_handler (context->priv->server,
                                          path,
                                          gupnp_acl_server_handler,
                                          handler,
-                                         (GDestroyNotify) gupnp_acl_server_handler_free);
+                                         (GDestroyNotify) acl_server_handler_free);
         } else
                 soup_server_add_handler (context->priv->server,
                                          path,
@@ -1526,6 +1460,20 @@ gupnp_context_add_server_handler (GUPnPContext *context,
                                          destroy);
 }
 
+void
+_gupnp_context_add_server_handler_with_data (GUPnPContext *context,
+                                             const char *path,
+                                             AclServerHandler *handler)
+{
+        g_return_if_fail (GUPNP_IS_CONTEXT (context));
+
+        soup_server_add_handler (context->priv->server,
+                                 path,
+                                 gupnp_acl_server_handler,
+                                 handler,
+                                 (GDestroyNotify) acl_server_handler_free);
+}
+
 /**
  * gupnp_context_remove_server_handler:
  * @context:
diff --git a/libgupnp/gupnp-service.c b/libgupnp/gupnp-service.c
index f904cbe..a6ff31a 100644
--- a/libgupnp/gupnp-service.c
+++ b/libgupnp/gupnp-service.c
@@ -31,6 +31,7 @@
 #include <gmodule.h>
 #include <libsoup/soup-date.h>
 #include <string.h>
+
 #include "gupnp-service.h"
 #include "gupnp-root-device.h"
 #include "gupnp-context-private.h"
@@ -915,7 +916,6 @@ control_server_handler (SoupServer                      *server,
         char *action_name;
         char *end;
         GUPnPServiceAction *action;
-        GUPnPAcl *acl;
 
         service = GUPNP_SERVICE (user_data);
 
@@ -1436,6 +1436,7 @@ gupnp_service_constructor (GType                  type,
         GObject *object;
         GUPnPServiceInfo *info;
         GUPnPContext *context;
+        AclServerHandler *handler;
         char *url;
         char *path;
 
@@ -1459,24 +1460,24 @@ gupnp_service_constructor (GType                  type,
         /* Run listener on controlURL */
         url = gupnp_service_info_get_control_url (info);
         path = path_from_url (url);
-        gupnp_context_add_server_handler (context,
-                                          TRUE,
-                                          path,
+        handler = acl_server_handler_new (GUPNP_SERVICE (object),
+                                          context,
                                           control_server_handler,
                                           object,
                                           NULL);
+        _gupnp_context_add_server_handler_with_data (context, path, handler);
         g_free (path);
         g_free (url);
 
         /* Run listener on eventSubscriptionURL */
         url = gupnp_service_info_get_event_subscription_url (info);
         path = path_from_url (url);
-        gupnp_context_add_server_handler (context,
-                                          TRUE,
-                                          path,
+        handler = acl_server_handler_new (GUPNP_SERVICE (object),
+                                          context,
                                           subscription_server_handler,
                                           object,
                                           NULL);
+        _gupnp_context_add_server_handler_with_data (context, path, handler);
         g_free (path);
         g_free (url);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]