[gupnp/wip/acl: 13/15] wip: Add helper function to register acl-protected soup handler



commit b54d903d9b29713fc3dabf39f44e23833fee052d
Author: Jens Georg <mail jensge org>
Date:   Sun Jan 19 13:44:16 2014 +0100

    wip: Add helper function to register acl-protected soup handler
    
    Signed-off-by: Jens Georg <mail jensge org>

 libgupnp/gupnp-context.c |  122 ++++++++++++++++++++++++++++++++++++++++++++++
 libgupnp/gupnp-context.h |    8 +++
 libgupnp/gupnp-service.c |   54 ++++++---------------
 3 files changed, 145 insertions(+), 39 deletions(-)
---
diff --git a/libgupnp/gupnp-context.c b/libgupnp/gupnp-context.c
index 3046c84..fa66f26 100644
--- a/libgupnp/gupnp-context.c
+++ b/libgupnp/gupnp-context.c
@@ -59,6 +59,49 @@
 
 #define GUPNP_CONTEXT_DEFAULT_LANGUAGE "en"
 
+typedef struct _GUPnPContextAclServerHandler
+{
+    GUPnPContext *context;
+    SoupServerHandler callback;
+    gpointer user_data;
+    GDestroyNotify notify;
+} GUPnPContextAclServerHandler;
+
+static GUPnPAclServerHandler *
+gupnp_acl_server_handler_new (GUPnPContext *context,
+                              SoupServerHandler callback,
+                              gpointer user_data,
+                              GDestroyNotify notify)
+{
+    GUPnPAclServerHandler *handler = g_new0 (GUPnPContextAclServerHandler);
+
+    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 (GUPnPAclServerHandler *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,
+                          const char *path,
+                          GHashTable *query,
+                          SoupClientContext *client,
+                          gpointer user_data);
+
 static void
 gupnp_context_initable_iface_init (gpointer g_iface,
                                    gpointer iface_data);
@@ -1336,3 +1379,82 @@ gupnp_context_set_acl (GUPnPContext *context, GUPnPAcl *acl)
 
         g_object_notify (G_OBJECT (context), "acl");
 }
+
+static void
+gupnp_acl_server_handler (SoupServer *server,
+                          SoupMessage *msg,
+                          const char *path,
+                          GHashTable *query,
+                          SoupClientContext *client,
+                          gpointer user_data)
+{
+    GUPnPContextAclServerHandler *handler = (GUPnPContextAclServerHandler *) user_data;
+
+    if (gupnp_acl_can_sync (handler->context->priv->acl)) {
+        if (!gupnp_acl_is_allowed (acl, soup_client_context_get_host (client))) {
+            soup_message_set_status (msg, SOUP_STATUS_FORBIDDEN);
+
+            return;
+        }
+    } else {
+        g_warning ("TBD: Handle async ACL");
+        soup_message_set_status (msg, SOUP_STATUS_FORBIDDEN);
+
+        return;
+    }
+
+    /* Delegate to orignal callback */
+    handler->callback (server, msg, path, query, client, handler->user_data);
+}
+
+/**
+ * gupnp_context_add_server_handler:
+ *
+ * Add a #SoupServerCallback to the #GUPnPContext<!-- -->'s #SoupServer.
+ *
+ * @context: a #GUPnPContext
+ * @use_acl: %TRUE, if the path should query the GUPnPContext::acl before
+ * serving the resource, %FALSE otherwise.
+ * @path: the toplevel path for the handler.
+ * @callback: callback to invoke for requests under @path
+ * @user_data:
+ * @destroy:
+ */
+void
+gupnp_context_add_server_handler (GUPnPContext *context,
+                                  gboolean use_acl,
+                                  const char *path,
+                                  SoupServerCallback callback,
+                                  gpointer user_data,
+                                  GDestroyNotify destroy)
+{
+        g_return_if_fail (GUPNP_IS_CONTEXT (context));
+
+        if (use_acl) {
+                GUPnPContextAclServerHandler *handler;
+                handler = gupnp_acl_server_handler_new (callback, user_data, destroy);
+                soup_server_add_handler (self->priv->server,
+                                         path,
+                                         gupnp_acl_server_handler,
+                                         handler,
+                                         (GDestroyNotify) gupnp_acl_server_handler_free);
+        } else
+                soup_server_add_handler (self->priv->server,
+                                         path,
+                                         callback,
+                                         user_data,
+                                         destroy);
+}
+
+/**
+ * gupnp_context_remove_server_handler:
+ * @context:
+ * @path:
+ */
+void
+gupnp_context_remove_server_handler (GUPnPContext *context, const char *path)
+{
+    g_return_if_fail (GUPNP_IS_CONTEXT (context));
+
+    soup_server_remove_handler (context->priv->server, path);
+}
diff --git a/libgupnp/gupnp-context.h b/libgupnp/gupnp-context.h
index d0556e9..233d2fa 100644
--- a/libgupnp/gupnp-context.h
+++ b/libgupnp/gupnp-context.h
@@ -137,6 +137,14 @@ gupnp_context_get_acl                  (GUPnPContext *context);
 void
 gupnp_context_set_acl                  (GUPnPContext *context,
                                         GUPnPAcl     *acl);
+
+void
+gupnp_context_add_server_handler       (GUPnPContext *context,
+                                        gboolean use_acl,
+                                        const char *path,
+                                        SoupServerCallback callback,
+                                        gpointer user_data,
+                                        GDestroyNotify destroy);
 G_END_DECLS
 
 #endif /* __GUPNP_CONTEXT_H__ */
diff --git a/libgupnp/gupnp-service.c b/libgupnp/gupnp-service.c
index faacc37..22e3cd6 100644
--- a/libgupnp/gupnp-service.c
+++ b/libgupnp/gupnp-service.c
@@ -941,20 +941,6 @@ control_server_handler (SoupServer                      *server,
 
         context = gupnp_service_info_get_context (GUPNP_SERVICE_INFO (service));
 
-        acl = gupnp_context_get_acl (context);
-
-        if (acl) {
-                if (gupnp_acl_can_sync (acl)) {
-                        if (!gupnp_acl_is_allowed (acl, "127.0.0.1")) {
-                                soup_message_set_status (msg, SOUP_STATUS_PROXY_UNAUTHORIZED);
-
-                                return;
-                        } else {
-                                g_warning ("TBD: Handle async ACL");
-                        }
-                }
-        }
-
         /* Get action name */
         soap_action = soup_message_headers_get_one (msg->request_headers,
                                                     "SOAPAction");
@@ -1324,20 +1310,6 @@ subscription_server_handler (G_GNUC_UNUSED SoupServer        *server,
 
         service = GUPNP_SERVICE (user_data);
 
-        context = gupnp_service_info_get_context (GUPNP_SERVICE_INFO (service));
-        acl = gupnp_context_get_acl (context);
-        if (acl) {
-                if (gupnp_acl_can_sync (acl)) {
-                        if (!gupnp_acl_is_allowed (acl, "127.0.0.1")) {
-                                soup_message_set_status (msg, SOUP_STATUS_PROXY_UNAUTHORIZED);
-
-                                return;
-                        } else {
-                                g_warning ("TBD: Handle async ACL");
-                        }
-                }
-        }
-
         callback = soup_message_headers_get_one (msg->request_headers,
                                                  "Callback");
         nt       = soup_message_headers_get_one (msg->request_headers, "NT");
@@ -1464,7 +1436,6 @@ gupnp_service_constructor (GType                  type,
         GObject *object;
         GUPnPServiceInfo *info;
         GUPnPContext *context;
-        SoupServer *server;
         char *url;
         char *path;
 
@@ -1475,7 +1446,7 @@ gupnp_service_constructor (GType                  type,
                                             n_construct_params,
                                             construct_params);
 
-        info    = GUPNP_SERVICE_INFO (object);
+        info = GUPNP_SERVICE_INFO (object);
 
         /* Get introspection and save state variable names */
         gupnp_service_info_get_introspection_async (info,
@@ -1484,21 +1455,28 @@ gupnp_service_constructor (GType                  type,
 
         /* Get server */
         context = gupnp_service_info_get_context (info);
-        server = gupnp_context_get_server (context);
 
         /* Run listener on controlURL */
         url = gupnp_service_info_get_control_url (info);
         path = path_from_url (url);
-        soup_server_add_handler (server, path,
-                                 control_server_handler, object, NULL);
+        gupnp_context_add_server_handler (context,
+                                          TRUE,
+                                          path,
+                                          control_server_handler,
+                                          object,
+                                          NULL);
         g_free (path);
         g_free (url);
 
         /* Run listener on eventSubscriptionURL */
         url = gupnp_service_info_get_event_subscription_url (info);
         path = path_from_url (url);
-        soup_server_add_handler (server, path,
-                                 subscription_server_handler, object, NULL);
+        gupnp_context_add_server_handler (context,
+                                          TRUE,
+                                          path,
+                                          subscription_server_handler,
+                                          object,
+                                          NULL);
         g_free (path);
         g_free (url);
 
@@ -1585,7 +1563,6 @@ gupnp_service_dispose (GObject *object)
         GObjectClass *object_class;
         GUPnPServiceInfo *info;
         GUPnPContext *context;
-        SoupServer *server;
         char *url;
         char *path;
 
@@ -1594,19 +1571,18 @@ gupnp_service_dispose (GObject *object)
         /* Get server */
         info = GUPNP_SERVICE_INFO (service);
         context = gupnp_service_info_get_context (info);
-        server = gupnp_context_get_server (context);
 
         /* Remove listener on controlURL */
         url = gupnp_service_info_get_control_url (info);
         path = path_from_url (url);
-        soup_server_remove_handler (server, path);
+        gupnp_context_remove_server_handler (server, path);
         g_free (path);
         g_free (url);
 
         /* Remove listener on eventSubscriptionURL */
         url = gupnp_service_info_get_event_subscription_url (info);
         path = path_from_url (url);
-        soup_server_remove_handler (server, path);
+        gupnp_context_remove_server_handler (server, path);
         g_free (path);
         g_free (url);
 


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