[PATCH 3/3] Add a Linux context manager



This is based on RT Netlink sockets, see rtnetlink(7)
---
 configure.ac                           |   28 ++-
 libgupnp/Makefile.am                   |   12 +
 libgupnp/gupnp-context-manager.c       |    3 +
 libgupnp/gupnp-linux-context-manager.c |  625 ++++++++++++++++++++++++++++++++
 libgupnp/gupnp-linux-context-manager.h |   73 ++++
 5 files changed, 740 insertions(+), 1 deletions(-)
 create mode 100644 libgupnp/gupnp-linux-context-manager.c
 create mode 100644 libgupnp/gupnp-linux-context-manager.h

diff --git a/configure.ac b/configure.ac
index e27428b..efc97f4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -44,7 +44,7 @@ PKG_CHECK_MODULES(GTHREAD, gthread-2.0)
 
 AC_ARG_WITH([context_manager],
             AS_HELP_STRING(
-                        [--with-context-manager=@<:@network-manager/unix@:>@],
+                        [--with-context-manager=@<:@network-manager/unix/linux@:>@],
                         [Context Manager backend to use]),,
             [with_context_manager="unix"])
 
@@ -54,6 +54,32 @@ AC_MSG_RESULT([${with_context_manager}])
 AM_CONDITIONAL([USE_NETWORK_MANAGER],
                [test "x$with_context_manager" = "xnetwork-manager"])
 
+USE_NETLINK=no
+if test "x$with_context_manager" = "xlinux"; then
+       dnl check for netlink (Linux)
+       AC_CHECK_HEADERS([sys/socket.h linux/rtnetlink.h],
+                        [ USE_NETLINK=yes ],
+                        [ USE_NETLINK=no ],
+                        [ #ifdef HAVE_SYS_SOCKET_H
+                          #include <sys/socket.h>
+                          #endif
+                        ])
+       if test x$USE_NETLINK =
+       then
+               AC_MSG_NOTICE([No rtnetlink found, falling back to unix context
+                              manager])
+       else
+               AC_CHECK_HEADERS([linux/wireless.h], [], [],
+                                [ #ifdef HAVE_SYS_SOCKET_H
+                                  #include <sys/socket.h>
+                                  #endif
+                                ])
+       fi
+fi
+
+AM_CONDITIONAL(USE_NETLINK, test x$USE_NETLINK = xyes)
+AC_SUBST(USE_NETLINK)
+
 # glib-genmarshal
 GLIB_GENMARSHAL=`pkg-config --variable=glib_genmarshal glib-2.0`
 AC_SUBST(GLIB_GENMARSHAL)
diff --git a/libgupnp/Makefile.am b/libgupnp/Makefile.am
index 51bd427..0f05b3b 100644
--- a/libgupnp/Makefile.am
+++ b/libgupnp/Makefile.am
@@ -9,8 +9,18 @@ CONTEXT_MANAGER_IMPL =
 CONTEXT_MANAGER_CFLAGS =
 endif
 
+if USE_NETLINK
+NETLINK_CFLAGS = -DUSE_NETLINK
+CONTEXT_MANAGER_IMPL += \
+			  gupnp-linux-context-manager.c		\
+			  gupnp-linux-context-manager.h
+else
+NETLINK_CFLAGS =
+endif
+
 AM_CFLAGS = $(LIBGUPNP_CFLAGS) \
 	    $(DBUS_GLIB_CFLAGS) \
+	    $(NETLINK_CFLAGS) \
 	    -I$(top_srcdir) \
 	    $(CONTEXT_MANAGER_CFLAGS)
 
@@ -87,6 +97,8 @@ libgupnp_1_0_la_LIBADD = $(LIBGUPNP_LIBS) $(DBUS_GLIB_LIBS) $(LIBCONIC_LIBS)
 EXTRA_DIST = gupnp-marshal.list 	   \
 	     gupnp-network-manager.c   	   \
 	     gupnp-network-manager.h       \
+	     gupnp-linux-context-manager.c \
+	     gupnp-linux-context-manager.h \
 	     gupnp-unix-context-manager.c  \
 	     gupnp-unix-context-manager.h
 
diff --git a/libgupnp/gupnp-context-manager.c b/libgupnp/gupnp-context-manager.c
index 193e8b7..3877cb6 100644
--- a/libgupnp/gupnp-context-manager.c
+++ b/libgupnp/gupnp-context-manager.c
@@ -373,6 +373,9 @@ gupnp_context_manager_new (GMainContext *main_context,
 
         if (gupnp_network_manager_is_available (main_context))
                 impl_type = GUPNP_TYPE_NETWORK_MANAGER;
+#elif USE_NETLINK
+#include "gupnp-linux-context-manager.h"
+        impl_type = GUPNP_TYPE_LINUX_CONTEXT_MANAGER;
 #endif
 
         if (impl_type == G_TYPE_INVALID)
diff --git a/libgupnp/gupnp-linux-context-manager.c b/libgupnp/gupnp-linux-context-manager.c
new file mode 100644
index 0000000..7f78fb3
--- /dev/null
+++ b/libgupnp/gupnp-linux-context-manager.c
@@ -0,0 +1,625 @@
+/*
+ * Copyright (C) 2011 Jens Georg
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:gupnp-linux-context-manager
+ * @short_description: Linux-specific implementation of #GUPnPContextManager
+ *
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#ifdef HAVE_LINUX_WIRELESS_H
+#include <linux/wireless.h>
+#endif
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <string.h>
+
+#include "gupnp-linux-context-manager.h"
+#include "gupnp-context.h"
+
+G_DEFINE_TYPE (GUPnPLinuxContextManager,
+               gupnp_linux_context_manager,
+               GUPNP_TYPE_CONTEXT_MANAGER);
+
+struct _GUPnPLinuxContextManagerPrivate {
+        int fd;
+        int nl_seq;
+        GSocket *netlink_socket;
+        GSource *netlink_socket_source;
+        GSource *bootstrap_source;
+
+        GHashTable *interfaces;
+};
+
+/* struct representing a network interface */
+struct _NetworkInterface {
+        GUPnPLinuxContextManager *manager;
+        int index;
+        char *name;
+        char *essid;
+
+        GUPnPContext *context;
+};
+
+typedef struct _NetworkInterface NetworkInterface;
+
+static NetworkInterface *
+network_device_new (GUPnPLinuxContextManager *manager,
+                    int index)
+{
+        NetworkInterface *device;
+        struct ifreq ifr;
+        int ret;
+
+        /* Query interface name */
+        memset (&ifr, 0, sizeof (struct ifreq));
+        ifr.ifr_ifindex = index;
+        ret = ioctl (manager->priv->fd, SIOCGIFNAME, &ifr);
+
+        if (ret == -1) {
+                g_warning ("Could not get interface name for index %d",
+                           index);
+
+                return NULL;
+        }
+
+        device = g_slice_new0 (NetworkInterface);
+        device->manager = manager;
+        device->name = g_strdup (ifr.ifr_name);
+
+        return device;
+}
+
+static char *
+get_essid (NetworkInterface *device)
+{
+#ifdef HAVE_LINUX_WIRELESS_H
+        char essid[IW_ESSID_MAX_SIZE + 1];
+        struct iwreq iwr;
+        int ret;
+
+        /* Query essid */
+        memset (&iwr, 0, sizeof (struct iwreq));
+        memset (essid, 0, IW_ESSID_MAX_SIZE + 1);
+        strncpy (iwr.ifr_name, device->name, IFNAMSIZ);
+        iwr.u.essid.pointer = (caddr_t) essid;
+        iwr.u.essid.length = IW_ESSID_MAX_SIZE;
+        ret = ioctl (device->manager->priv->fd, SIOCGIWESSID, &iwr);
+
+        if (ret == 0 && essid[0] != '\0')
+                return g_strdup (essid);
+#endif
+        return NULL;
+}
+
+static void
+network_device_create_context (NetworkInterface *device)
+{
+        GMainContext *main_context;
+        guint port;
+        GError *error = NULL;
+
+        g_object_get (device->manager,
+                      "main-context", &main_context,
+                      "port", &port,
+                      NULL);
+
+        device->essid = get_essid (device);
+        device->context = g_initable_new (GUPNP_TYPE_CONTEXT,
+                                          NULL,
+                                          &error,
+                                          "main-context", main_context,
+                                          "interface", device->name,
+                                          "network", device->essid,
+                                          "port", port);
+        if (error) {
+                g_warning ("Error creating GUPnP context: %s",
+                           error->message);
+                g_error_free (error);
+
+                return;
+        }
+
+        g_signal_emit_by_name (device->manager,
+                               "context-available",
+                               device->context);
+}
+
+static void
+network_device_free (NetworkInterface *device)
+{
+        if (device->name != NULL)
+                g_free (device->name);
+        if (device->essid != NULL)
+                g_free (device->essid);
+
+        if (device->context != NULL) {
+                g_signal_emit_by_name (device->manager,
+                                       "context-unavailable",
+                                       device->context);
+
+                g_object_unref (device->context);
+        }
+}
+
+
+static void query_all_network_interfaces (GUPnPLinuxContextManager *self);
+static void query_all_addresses (GUPnPLinuxContextManager *self);
+static void receive_netlink_message (GUPnPLinuxContextManager  *self,
+                                     GError                   **error);
+static void create_context (GUPnPLinuxContextManager *self,
+                            struct ifaddrmsg         *ifa);
+static void remove_context (GUPnPLinuxContextManager *self,
+                            struct ifaddrmsg         *ifa);
+
+#define RT_ATTR_OK(a,l) \
+        ((l > 0) && RTA_OK (a, l))
+
+static gboolean
+on_netlink_message_available (GSocket      *socket,
+                              GIOCondition  condition,
+                              gpointer      user_data)
+{
+        GUPnPLinuxContextManager *self;
+
+        self = GUPNP_LINUX_CONTEXT_MANAGER (user_data);
+
+        receive_netlink_message (self, NULL);
+
+        return TRUE;
+}
+
+
+
+static gboolean
+is_wireless_status_message (struct nlmsghdr *header)
+{
+        int rt_attr_len;
+        struct rtattr *rt_attr;
+
+        rt_attr = IFLA_RTA (NLMSG_DATA (header));
+        rt_attr_len = IFLA_PAYLOAD (header);
+        while (RT_ATTR_OK (rt_attr, rt_attr_len)) {
+                if (rt_attr->rta_type == IFLA_WIRELESS)
+                        return TRUE;
+
+                rt_attr = RTA_NEXT(rt_attr, rt_attr_len);
+        }
+
+        return FALSE;
+}
+
+void
+create_context (GUPnPLinuxContextManager *self, struct ifaddrmsg *ifa)
+{
+        NetworkInterface *device;
+
+        remove_context (self, ifa);
+
+        device = g_hash_table_lookup (self->priv->interfaces,
+                                      GINT_TO_POINTER (ifa->ifa_index));
+        if (!device) {
+                g_warning ("Got new address for device %d but device is not active",
+                           ifa->ifa_index);
+
+                return;
+        }
+
+        network_device_create_context (device);
+}
+
+void
+remove_context (GUPnPLinuxContextManager *self, struct ifaddrmsg *ifa)
+{
+        NetworkInterface *device;
+
+        device = g_hash_table_lookup (self->priv->interfaces,
+                                      GINT_TO_POINTER (ifa->ifa_index));
+
+        if (device && device->context) {
+                g_signal_emit_by_name (self,
+                                       "context-unavailable",
+                                       device->context);
+                g_object_unref (device->context);
+
+                device->context = NULL;
+        }
+}
+
+static gboolean
+on_bootstrap (GUPnPLinuxContextManager *self)
+{
+        if (self->priv->nl_seq == 0) {
+                query_all_network_interfaces (self);
+
+                return TRUE;
+        } else if (self->priv->nl_seq == 1) {
+                query_all_addresses (self);
+
+                return TRUE;
+        } else {
+                GMainContext *main_context;
+
+                self->priv->netlink_socket_source = g_socket_create_source
+                                                (self->priv->netlink_socket,
+                                                 G_IO_IN | G_IO_PRI,
+                                                 NULL);
+                g_object_get (self,
+                              "main-context", &main_context,
+                              NULL);
+
+                g_source_attach (self->priv->netlink_socket_source,
+                                 main_context);
+
+                g_source_set_callback (self->priv->netlink_socket_source,
+                                       (GSourceFunc) on_netlink_message_available,
+                                       self,
+                                       NULL);
+        }
+
+        return FALSE;
+}
+
+struct nl_req_s {
+        struct nlmsghdr hdr;
+        struct rtgenmsg gen;
+};
+
+static void
+send_netlink_request (GUPnPLinuxContextManager *self,
+                      guint netlink_message,
+                      guint flags)
+{
+        struct nl_req_s req;
+        struct sockaddr_nl dest;
+        struct msghdr msg;
+        struct iovec io;
+
+        memset (&req, 0, sizeof (req));
+        memset (&dest, 0, sizeof (dest));
+        memset (&msg, 0, sizeof (msg));
+
+        dest.nl_family = AF_NETLINK;
+        req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
+        req.hdr.nlmsg_seq = self->priv->nl_seq++;
+        req.hdr.nlmsg_type = netlink_message;
+        req.hdr.nlmsg_flags = NLM_F_REQUEST | flags;
+        req.gen.rtgen_family = AF_INET;
+
+        io.iov_base = &req;
+        io.iov_len = req.hdr.nlmsg_len;
+
+        msg.msg_iov = &io;
+        msg.msg_iovlen = 1;
+        msg.msg_name = &dest;
+        msg.msg_namelen = sizeof (dest);
+
+        if (sendmsg (g_socket_get_fd (self->priv->netlink_socket),
+                 (struct msghdr *) &msg,
+                 0) < 0) {
+                g_warning ("Could not send netlink message: %s",
+                           strerror (errno));
+        }
+}
+
+static void
+query_all_network_interfaces (GUPnPLinuxContextManager *self)
+{
+        GError *error = NULL;
+
+        send_netlink_request (self,
+                              RTM_GETLINK,
+                              NLM_F_DUMP);
+        do {
+                receive_netlink_message (self, &error);
+        } while (error == NULL);
+}
+
+static void
+query_all_addresses (GUPnPLinuxContextManager *self)
+{
+        send_netlink_request (self,
+                              RTM_GETADDR,
+                              NLM_F_ROOT | NLM_F_MATCH | NLM_F_ACK);
+}
+
+#define NLMSG_IS_VALID(msg,len) \
+        (NLMSG_OK(msg,len) && (msg->nlmsg_type != NLMSG_DONE))
+
+static void
+handle_link_message (GUPnPLinuxContextManager *self,
+                     struct ifinfomsg         *ifi)
+{
+        gpointer key;
+
+        if (ifi->ifi_flags & IFF_POINTOPOINT)
+                return;
+
+        /* Ignore non-multicast interfaces, except lo */
+        if (!(ifi->ifi_flags & IFF_MULTICAST || ifi->ifi_flags & IFF_LOOPBACK))
+                return;
+
+        key = GINT_TO_POINTER (ifi->ifi_index);
+        if (ifi->ifi_flags & IFF_UP) {
+                if (g_hash_table_lookup (self->priv->interfaces,
+                                         key) == NULL) {
+                        NetworkInterface *device;
+
+                        device = network_device_new (self, ifi->ifi_index);
+
+                        if (device)
+                                g_hash_table_insert (self->priv->interfaces,
+                                                     key,
+                                                     device);
+                }
+        } else
+                g_hash_table_remove (self->priv->interfaces, key);
+}
+
+static void
+receive_netlink_message (GUPnPLinuxContextManager *self, GError **error)
+{
+        static char buf[4096];
+        static const int bufsize = 4096;
+
+        int len;
+        GError *inner_error = NULL;
+        struct nlmsghdr *header = (struct nlmsghdr *) buf;
+        struct ifinfomsg *ifi;
+        struct ifaddrmsg *ifa;
+
+
+        len = g_socket_receive (self->priv->netlink_socket,
+                                buf,
+                                bufsize,
+                                NULL,
+                                &inner_error);
+        if (len == -1) {
+                if (inner_error->code != G_IO_ERROR_WOULD_BLOCK)
+                        g_warning ("Error receiving netlink message: %s",
+                                   inner_error->message);
+                g_propagate_error (error, inner_error);
+
+                return;
+        }
+
+        for (;NLMSG_IS_VALID(header, len); header = NLMSG_NEXT(header,len)) {
+                switch (header->nlmsg_type) {
+                        case RTM_NEWADDR:
+                                ifa = NLMSG_DATA (header);
+                                create_context (self, ifa);
+                                break;
+                        case RTM_DELADDR:
+                                ifa = NLMSG_DATA (header);
+                                remove_context (self, ifa);
+                                break;
+                        case RTM_NEWLINK:
+                                /* Check if wireless is up for chit-chat */
+                                if (is_wireless_status_message (header))
+                                        continue;
+                        case RTM_DELLINK:
+                                ifi = NLMSG_DATA (header);
+                                handle_link_message (self, ifi);
+                                break;
+                        case NLMSG_ERROR:
+                                break;
+                        default:
+                                break;
+                }
+        }
+}
+
+/* Create INET socket used for SIOCGIFNAME and SIOCGIWESSID ioctl
+ * calls */
+static gboolean
+create_ioctl_socket (GUPnPLinuxContextManager *self, GError **error)
+{
+        self->priv->fd = socket (AF_INET, SOCK_DGRAM, 0);
+
+        if (self->priv->fd < 0) {
+                self->priv->fd = 0;
+
+                g_set_error_literal (error,
+                                     G_IO_ERROR,
+                                     g_io_error_from_errno (errno),
+                                     "Failed to setup socket for ioctl");
+
+                return FALSE;
+        }
+
+        return TRUE;
+}
+
+/* Create a netlink socket, bind to it and wrap it in a GSocket */
+static gboolean
+create_netlink_socket (GUPnPLinuxContextManager *self, GError **error)
+{
+        struct sockaddr_nl sa;
+        int fd, status;
+        GSocket *sock;
+        GError *inner_error;
+
+        inner_error = NULL;
+
+        fd = socket (PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
+        if (fd == -1) {
+                g_set_error_literal (error,
+                                     G_IO_ERROR,
+                                     g_io_error_from_errno (errno),
+                                     "Failed to bind to netlink socket");
+                return FALSE;
+        }
+
+        /* Listen for interface changes and IP address changes */
+        memset (&sa, 0, sizeof (sa));
+        sa.nl_family = AF_NETLINK;
+        sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;
+
+        status = bind (fd, (struct sockaddr *) &sa, sizeof (sa));
+        if (status == -1) {
+                g_set_error_literal (error,
+                                     G_IO_ERROR,
+                                     g_io_error_from_errno (errno),
+                                     "Failed to bind to netlink socket");
+                close (fd);
+
+                return FALSE;
+        }
+
+        sock = g_socket_new_from_fd (fd, &inner_error);
+        if (sock == NULL) {
+                close (fd);
+                g_propagate_prefixed_error (error,
+                                            inner_error,
+                                            "Failed to create GSocket from "
+                                            "netlink socket");
+
+                return FALSE;
+        }
+
+        g_socket_set_blocking (sock, FALSE);
+
+        self->priv->netlink_socket = sock;
+
+        return TRUE;
+}
+
+static void
+gupnp_linux_context_manager_init (GUPnPLinuxContextManager *self)
+{
+        self->priv =
+                G_TYPE_INSTANCE_GET_PRIVATE (self,
+                                             GUPNP_TYPE_LINUX_CONTEXT_MANAGER,
+                                             GUPnPLinuxContextManagerPrivate);
+
+        self->priv->nl_seq = 0;
+
+        self->priv->interfaces =
+                g_hash_table_new_full (g_direct_hash,
+                                       g_direct_equal,
+                                       NULL,
+                                       (GDestroyNotify) network_device_free);
+}
+
+static void
+gupnp_linux_context_manager_constructed (GObject *object)
+{
+        GObjectClass *parent_class;
+        GUPnPLinuxContextManager *self;
+        GError *error = NULL;
+        GMainContext *main_context;
+
+        self = GUPNP_LINUX_CONTEXT_MANAGER (object);
+
+        g_object_get (self,
+                      "main-context", &main_context,
+                      NULL);
+
+        if (!create_ioctl_socket (self, &error))
+                goto cleanup;
+
+        if (!create_netlink_socket (self, &error))
+                goto cleanup;
+
+        self->priv->bootstrap_source =
+                                g_idle_source_new ();
+        g_source_attach (self->priv->bootstrap_source,
+                         main_context);
+        g_source_set_callback (self->priv->bootstrap_source,
+                               (GSourceFunc) on_bootstrap,
+                               self,
+                               NULL);
+cleanup:
+        if (error) {
+                if (self->priv->fd > 0)
+                        close (self->priv->fd);
+
+                g_warning ("Failed to setup Linux context manager: %s",
+                           error->message);
+
+                g_error_free (error);
+        }
+
+        /* Chain-up */
+        parent_class = G_OBJECT_CLASS (gupnp_linux_context_manager_parent_class);
+        if (parent_class->constructed)
+                parent_class->constructed (object);
+}
+
+static void
+gupnp_linux_context_manager_dispose (GObject *object)
+{
+        GUPnPLinuxContextManager *self;
+        GObjectClass *parent_class;
+
+        self = GUPNP_LINUX_CONTEXT_MANAGER (object);
+
+        if (self->priv->bootstrap_source != NULL) {
+                g_source_destroy (self->priv->bootstrap_source);
+                g_source_unref (self->priv->bootstrap_source);
+                self->priv->bootstrap_source = NULL;
+        }
+
+        if (self->priv->netlink_socket_source != NULL) {
+               g_source_destroy (self->priv->netlink_socket_source);
+               g_source_unref (self->priv->netlink_socket_source);
+               self->priv->netlink_socket_source = NULL;
+        }
+
+        if (self->priv->netlink_socket != NULL) {
+                g_object_unref (self->priv->netlink_socket);
+                self->priv->netlink_socket = NULL;
+        }
+
+        if (self->priv->fd != 0) {
+                close (self->priv->fd);
+                self->priv->fd = 0;
+        }
+
+        if (self->priv->interfaces) {
+                g_hash_table_destroy (self->priv->interfaces);
+                self->priv->interfaces = NULL;
+        }
+
+        /* Chain-up */
+        parent_class = G_OBJECT_CLASS (gupnp_linux_context_manager_parent_class);
+        parent_class->dispose (object);
+}
+
+static void
+gupnp_linux_context_manager_class_init (GUPnPLinuxContextManagerClass *klass)
+{
+        GObjectClass *object_class;
+
+        object_class = G_OBJECT_CLASS (klass);
+
+        object_class->constructed = gupnp_linux_context_manager_constructed;
+        object_class->dispose     = gupnp_linux_context_manager_dispose;
+
+        g_type_class_add_private (klass,
+                                  sizeof (GUPnPLinuxContextManagerPrivate));
+}
diff --git a/libgupnp/gupnp-linux-context-manager.h b/libgupnp/gupnp-linux-context-manager.h
new file mode 100644
index 0000000..263258b
--- /dev/null
+++ b/libgupnp/gupnp-linux-context-manager.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2011 Jens Georg.
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GUPNP_LINUX_CONTEXT_MANAGER_H__
+#define __GUPNP_LINUX_CONTEXT_MANAGER_H__
+
+#include "gupnp-context-manager.h"
+
+G_BEGIN_DECLS
+
+GType
+gupnp_linux_context_manager_get_type (void) G_GNUC_CONST;
+
+#define GUPNP_TYPE_LINUX_CONTEXT_MANAGER \
+                (gupnp_linux_context_manager_get_type ())
+#define GUPNP_LINUX_CONTEXT_MANAGER(obj) \
+                (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+                 GUPNP_TYPE_LINUX_CONTEXT_MANAGER, \
+                 GUPnPLinuxContextManager))
+#define GUPNP_LINUX_CONTEXT_MANAGER_CLASS(obj) \
+                (G_TYPE_CHECK_CLASS_CAST ((obj), \
+                 GUPNP_TYPE_LINUX_CONTEXT_MANAGER, \
+                 GUPnPLinuxContextManagerClass))
+#define GUPNP_IS_LINUX_CONTEXT_MANAGER(obj) \
+                (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+                 GUPNP_TYPE_LINUX_CONTEXT_MANAGER))
+#define GUPNP_IS_LINUX_CONTEXT_MANAGER_CLASS(obj) \
+                (G_TYPE_CHECK_CLASS_TYPE ((obj), \
+                 GUPNP_TYPE_LINUX_CONTEXT_MANAGER))
+#define GUPNP_LINUX_CONTEXT_MANAGER_GET_CLASS(obj) \
+                (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+                 GUPNP_TYPE_LINUX_CONTEXT_MANAGER, \
+                 GUPnPLinuxContextManagerClass))
+
+typedef struct _GUPnPLinuxContextManagerPrivate GUPnPLinuxContextManagerPrivate;
+
+typedef struct {
+        GUPnPContextManager parent;
+
+        GUPnPLinuxContextManagerPrivate *priv;
+} GUPnPLinuxContextManager;
+
+typedef struct {
+        GUPnPContextManagerClass parent_class;
+
+        /* future padding */
+        void (* _gupnp_reserved1) (void);
+        void (* _gupnp_reserved2) (void);
+        void (* _gupnp_reserved3) (void);
+        void (* _gupnp_reserved4) (void);
+} GUPnPLinuxContextManagerClass;
+
+G_END_DECLS
+
+#endif /* __GUPNP_LINUX_CONTEXT_MANAGER_H__ */
-- 
1.7.5.4



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