[systemd-devel] [PATCH 2/4] gdbus: Add preliminary implementation of kdbus support

Karol Lewandowski k.lewandowsk at samsung.com
Thu Nov 21 03:33:50 PST 2013


---
 gio/gkdbus.c           | 1112 ++++++++++++++++++++++++++++++++++++++++++++++++
 gio/gkdbus.h           |  113 +++++
 gio/gkdbusconnection.c |  196 +++++++++
 gio/gkdbusconnection.h |   91 ++++
 4 files changed, 1512 insertions(+)
 create mode 100644 gio/gkdbus.c
 create mode 100644 gio/gkdbus.h
 create mode 100644 gio/gkdbusconnection.c
 create mode 100644 gio/gkdbusconnection.h

diff --git a/gio/gkdbus.c b/gio/gkdbus.c
new file mode 100644
index 0000000..5f6459e
--- /dev/null
+++ b/gio/gkdbus.c
@@ -0,0 +1,1112 @@
+/*  GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright © 2013 Samsung Electronics
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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.
+ *
+ * Author: Michal Eljasiewicz   <m.eljasiewic at samsung.com>
+ * Author: Lukasz Skalski       <l.skalski at partner.samsung.com>
+ */
+
+#include "config.h"
+
+#include "gkdbus.h"
+#include "glib-unix.h"
+
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <stdio.h>
+
+#ifdef HAVE_SYS_FILIO_H
+# include <sys/filio.h>
+#endif
+
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+
+#include "gcancellable.h"
+#include "gioenumtypes.h"
+#include "ginitable.h"
+#include "gioerror.h"
+#include "gioenums.h"
+#include "gioerror.h"
+#include "glibintl.h"
+#include "kdbus.h"
+#include "gdbusmessage.h"
+#include "gdbusconnection.h"
+
+#define KDBUS_PART_FOREACH(part, head, first)                           \
+        for (part = (head)->first;                                      \
+             (guint8 *)(part) < (guint8 *)(head) + (head)->size;        \
+             part = KDBUS_PART_NEXT(part))
+
+#define KDBUS_PART_HEADER_SIZE offsetof(struct kdbus_item, data)
+
+/* Size of memory registered with Kdbus for receiving messages */
+#define RECEIVE_POOL_SIZE (10 * 1024LU * 1024LU)
+
+/* Size of message over which memfd transport is used */
+#define MEMFD_SIZE_THRESHOLD (2 * 1024 * 1024LU)
+
+#define MSG_ITEM_BUILD_VEC(data, datasize)                               \
+        item->type = KDBUS_MSG_PAYLOAD_VEC;                              \
+        item->size = KDBUS_PART_HEADER_SIZE + sizeof(struct kdbus_vec);  \
+        item->vec.address = (unsigned long) data;                        \
+        item->vec.size = datasize;
+
+#define KDBUS_ALIGN8(l) (((l) + 7) & ~7)
+#define KDBUS_PART_NEXT(part) \
+        (typeof(part))(((guint8 *)part) + KDBUS_ALIGN8((part)->size))
+#define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8((s) + KDBUS_PART_HEADER_SIZE)
+
+/*
+ * SECTION:gkdbus
+ * @short_description: Low-level kdbus object
+ * @include: gio/gio.h
+ *
+ * A #GKdbus is a lowlevel adapter for Kdbus IPC solution. It is meant
+ * to replace DBUS  as fundamental IPC solution for  Linux, however it
+ * is  still experimental  work in  progress.  You  may  find detailed
+ * description in kdbus.txt at https://github.com/gregkh/kdbus
+ *
+ * Dbus-daemon  use  is  now  limited only  to  administrative  tasks,
+ * message routing is done in kernel which is faster.
+ *
+ * There are two modes of transport - "vectors" and "memfd".
+ * Vector   is  standard   and   for  smaller   messages,  less   than
+ * MEMFD_SIZE_THRESHOLD.   Memfd is  special case,  designed  for bulk
+ * data, with message size over MEMFD_SIZE_THRESHOLD.
+ *
+ * Some Kdbus  messages e.g. error messages  and Hello msg  need to be
+ * converted and passed to  client. For this adaptation reply messages
+ * are fabricated locally and inserted into incoming message queue.
+ *
+ *
+ */
+
+static void     g_kdbus_initable_iface_init (GInitableIface  *iface);
+static gboolean g_kdbus_initable_init       (GInitable       *initable,
+                                             GCancellable    *cancellable,
+                                             GError         **error);
+
+G_DEFINE_TYPE_WITH_CODE (GKdbus, g_kdbus, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
+                                                g_kdbus_initable_iface_init));
+
+enum
+{
+  PROP_0,
+  PROP_FD,
+  PROP_TIMEOUT,
+  PROP_PEER_ID
+};
+
+struct _GKdbusPrivate
+{
+  gint            fd;
+  gchar          *path;
+  gchar          *buffer_ptr;
+  gchar          *sender;
+  gint            peer_id;
+  guint64         bloom_size;
+  guint           registered : 1;
+  guint           closed : 1;
+  guint           inited : 1;
+  guint           timeout;
+  guint           timed_out : 1;
+  gint            memfd;
+  guint64         __attribute__ ((__aligned__(8))) offset;
+  gchar          *msg_buffer_ptr;
+};
+
+/*
+ * g_kdbus_get_property:
+ *
+ */
+static void
+g_kdbus_get_property (GObject      *object,
+                      guint        prop_id,
+                      GValue      *value,
+                      GParamSpec  *pspec)
+{
+  GKdbus *kdbus = G_KDBUS (object);
+
+  switch (prop_id)
+    {
+      case PROP_FD:
+        g_value_set_int (value, kdbus->priv->fd);
+        break;
+
+      case PROP_TIMEOUT:
+        g_value_set_int (value, kdbus->priv->timeout);
+        break;
+
+      case PROP_PEER_ID:
+        g_value_set_int (value, kdbus->priv->peer_id);
+        break;
+
+      default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+/*
+ * g_kdbus_set_property:
+ *
+ */
+static void
+g_kdbus_set_property (GObject        *object,
+                       guint          prop_id,
+                       const GValue  *value,
+                       GParamSpec    *pspec)
+{
+  GKdbus *kdbus = G_KDBUS (object);
+
+  switch (prop_id)
+    {
+      case PROP_TIMEOUT:
+        kdbus->priv->timeout = g_value_get_int (value);
+        break;
+
+      default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+/*
+ * g_kdbus_finalize:
+ *
+ * TODO: Compare with gsocket
+ */
+static void
+g_kdbus_finalize (GObject  *object)
+{
+  GKdbus *kdbus = G_KDBUS (object);
+
+  if (kdbus->priv->fd != -1 && !kdbus->priv->closed)
+    g_kdbus_close (kdbus, NULL);
+
+  if (G_OBJECT_CLASS (g_kdbus_parent_class)->finalize)
+    (*G_OBJECT_CLASS (g_kdbus_parent_class)->finalize) (object);
+
+}
+
+/*
+ * g_kdbus_class_init:
+ *
+ */
+static void
+g_kdbus_class_init (GKdbusClass  *klass)
+{
+  GObjectClass *gobject_class G_GNUC_UNUSED = G_OBJECT_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (GKdbusPrivate));
+
+  gobject_class->finalize = g_kdbus_finalize;
+  gobject_class->set_property = g_kdbus_set_property;
+  gobject_class->get_property = g_kdbus_get_property;
+}
+
+/*
+ * g_kdbus_initable_iface_init:
+ *
+ */
+static void
+g_kdbus_initable_iface_init (GInitableIface *iface)
+{
+  iface->init = g_kdbus_initable_init;
+}
+
+/*
+ * g_kdbus_init:
+ */
+static void
+g_kdbus_init (GKdbus  *kdbus)
+{
+  kdbus->priv = G_TYPE_INSTANCE_GET_PRIVATE (kdbus, G_TYPE_KDBUS, GKdbusPrivate);
+
+  kdbus->priv->fd = -1;
+  kdbus->priv->peer_id = -1;
+  kdbus->priv->bloom_size = 0;
+  kdbus->priv->path = NULL;
+  kdbus->priv->buffer_ptr = NULL;
+  kdbus->priv->sender = NULL;
+  kdbus->priv->memfd = 0;
+}
+
+/*
+ * g_kdbus_initable_init:
+ *
+ */
+static gboolean
+g_kdbus_initable_init (GInitable     *initable,
+                       GCancellable  *cancellable,
+                       GError       **error)
+{
+  GKdbus  *kdbus;
+
+  g_return_val_if_fail (G_IS_KDBUS (initable), FALSE);
+
+  kdbus = G_KDBUS (initable);
+
+  if (cancellable != NULL)
+    {
+      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+                           _("Cancellable initialization not supported"));
+      return FALSE;
+    }
+
+  kdbus->priv->inited = TRUE;
+
+  return TRUE;
+}
+
+/**
+ * g_kdbus_init_memfd:
+ * @kdbus: a #GKdbus.
+ *
+ * Retrieves file descriptor to memory pool from kdbus module.
+ * It is then used for bulk data sending.
+ * Triggered when message payload is over MEMFD_SIZE_THRESHOLD
+ *
+ */
+static gint
+g_kdbus_init_memfd (GKdbus  *kdbus)
+{
+  if (ioctl(kdbus->priv->fd, KDBUS_CMD_MEMFD_NEW, &kdbus->priv->memfd) < 0) {
+    g_error(" KDBUS_DEBUG: (%s()): error when KDBUS_CMD_MEMFD_NEW: %m, %d",__FUNCTION__,errno);
+    return -1;
+  }
+
+#ifdef KDBUS_DEBUG
+  g_print (" KDBUS_DEBUG: (%s()): memfd=%i\n",__FUNCTION__, kdbus->priv->memfd);
+#endif
+
+  return 0;
+}
+
+/**
+ * g_kdbus_open:
+ * @kdbus: a #GKdbus.
+ * @address: path to kdbus bus file.
+ * @cancellable: (allow-none): a %GCancellable or %NULL
+ * @error: #GError for error reporting, or %NULL to ignore.
+ *
+ * Opens file descriptor to Kdbus bus control.
+ * It is located in /dev/kdbus/uid-name/bus. Dbus-daemon creates it on startup.
+ * TODO handle cancellable and error
+ *
+ * Returns: TRUE on success.
+ */
+gboolean
+g_kdbus_open (GKdbus        *kdbus,
+              const gchar   *address,
+              GCancellable  *cancellable,
+              GError       **error)
+{
+  g_return_val_if_fail (G_IS_KDBUS (kdbus), FALSE);
+  kdbus->priv->fd = open(address, O_RDWR|O_CLOEXEC|O_NONBLOCK);
+
+  if (kdbus->priv->fd<0)
+    {
+      g_error(" KDBUS_DEBUG: (%s()): error when mmap: %m, %d",__FUNCTION__,errno);
+      return FALSE;
+    }
+
+#ifdef KDBUS_DEBUG
+  g_print (" KDBUS_DEBUG: (%s()): kdbus endpoint opened\n",__FUNCTION__);
+#endif
+
+  kdbus->priv->closed = FALSE;
+  return TRUE;
+}
+
+/**
+ * g_kdbus_close:
+ * @kdbus: a #GKdbus.
+ * @error: #GError for error reporting, or %NULL to ignore.
+ *
+ * Closes file descriptor to Kdbus bus.
+ *
+ * Returns: TRUE on success.
+ *
+ */
+gboolean
+g_kdbus_close (GKdbus  *kdbus,
+               GError  **error)
+{
+  g_return_val_if_fail (G_IS_KDBUS (kdbus), FALSE);
+  close(kdbus->priv->fd);
+
+  kdbus->priv->closed = TRUE;
+  kdbus->priv->fd = -1;
+  kdbus->priv->registered = FALSE;
+
+#ifdef KDBUS_DEBUG
+  g_print (" KDBUS_DEBUG: (%s()): kdbus endpoint closed\n",__FUNCTION__);
+#endif
+
+  return TRUE;
+}
+
+/**
+ * g_kdbus_is_closed:
+ * @kdbus: a #GKdbus.
+ *
+ * checks whether a kdbus is closed.
+ *
+ */
+gboolean
+g_kdbus_is_closed (GKdbus *kdbus)
+{
+  g_return_val_if_fail (G_IS_KDBUS (kdbus), FALSE);
+
+  return kdbus->priv->closed;
+}
+
+/**
+ * g_kdbus_register:
+ * @kdbus: a #GKdbus.
+ *
+ * Hello message to get unique name on bus in return
+ * Finally mapping memory for incoming messages
+ *
+ * Returns: TRUE on success.
+ *
+ */
+gboolean
+g_kdbus_register (GKdbus *kdbus)
+{
+  struct kdbus_cmd_hello __attribute__ ((__aligned__(8))) hello;
+
+  hello.conn_flags = KDBUS_HELLO_ACCEPT_FD
+    | KDBUS_HELLO_ATTACH_COMM
+    | KDBUS_HELLO_ATTACH_EXE
+    | KDBUS_HELLO_ATTACH_CMDLINE
+    | KDBUS_HELLO_ATTACH_CAPS
+    | KDBUS_HELLO_ATTACH_CGROUP
+    | KDBUS_HELLO_ATTACH_SECLABEL
+    | KDBUS_HELLO_ATTACH_AUDIT;
+
+  hello.size = sizeof(struct kdbus_cmd_hello);
+  hello.pool_size = RECEIVE_POOL_SIZE;
+
+  if (ioctl(kdbus->priv->fd, KDBUS_CMD_HELLO, &hello))
+    {
+      g_error(" KDBUS_DEBUG: (%s()): fd=%d failed to send hello: %m, %d",__FUNCTION__,kdbus->priv->fd,errno);
+      return FALSE;
+    }
+
+  kdbus->priv->registered = TRUE;
+  kdbus->priv->peer_id = hello.id;
+
+#ifdef KDBUS_DEBUG
+  g_print(" KDBUS_DEBUG: (%s()): Our peer ID=%llu\n",__FUNCTION__,hello.id);
+#endif
+
+  kdbus->priv->bloom_size = hello.bloom_size;
+  kdbus->priv->buffer_ptr = mmap(NULL, RECEIVE_POOL_SIZE, PROT_READ, MAP_SHARED, kdbus->priv->fd, 0);
+
+  if (kdbus->priv->buffer_ptr == MAP_FAILED)
+    {
+      g_error(" KDBUS_DEBUG: (%s()): error when mmap: %m, %d",__FUNCTION__,errno);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+/**
+ * g_kdbus_generate_local_dbus_reply:
+ * @message: outgoing message from client
+ * @message_type: whether is error
+ * @message_flags: flags copied
+ * @message_body: what to put in reply
+ * @error_name: name of error or %NULL
+ *
+ * Fabricates reply to message that we wanted to send to dbus-daemon.
+ * It is neccessary because Kdbus response is not compatible with DBUS
+ * and has to be translated.
+ *
+ * Returns: generated reply to self.
+ *
+ */
+static GDBusMessage *
+g_kdbus_generate_local_dbus_msg (GDBusMessage       *message,
+                                 GDBusMessageType    message_type,
+                                 GDBusMessageFlags   message_flags,
+                                 GVariant           *message_body,
+                                 const gchar        *error_name)
+{
+  GDBusMessage *new_message;
+
+  new_message = g_dbus_message_new ();
+
+  g_dbus_message_set_sender (new_message, "org.freedesktop.DBus");
+  g_dbus_message_set_message_type (new_message, message_type);
+  g_dbus_message_set_flags (new_message, message_flags);
+
+  g_dbus_message_set_body (new_message, message_body);
+
+  if (message != NULL)
+    {
+      g_dbus_message_set_destination (new_message, g_dbus_message_get_sender (message));
+      g_dbus_message_set_reply_serial (new_message, g_dbus_message_get_serial (message));
+    }
+
+  if (message_type == G_DBUS_MESSAGE_TYPE_ERROR)
+    g_dbus_message_set_error_name (new_message, error_name);
+
+  if (G_UNLIKELY (_g_dbus_debug_message ()))
+    {
+      gchar *s;
+      _g_dbus_debug_print_lock ();
+      g_print ("========================================================================\n"
+               "GDBus-debug:Message:\n"
+               "  <<<< RECEIVED LOCAL D-Bus message (N/A bytes)\n");
+
+      s = g_dbus_message_print (new_message, 2);
+      g_print ("%s", s);
+      g_free (s);
+      _g_dbus_debug_print_unlock ();
+    }
+
+    return new_message;
+}
+
+/**
+ * g_kdbus_decode_msg:
+ * @kdbus: a #GKdbus.
+ * @msg: Kdbus message to be unpacked.
+ *
+ * Kdbus message is made of items. For data, it can be vectors or memfd.
+ * Unpacks DBUS message data from Kdbus message items.
+ * For errors received from Kdbus, DBUS messages are fabricated end sent
+ * back to self, by inserting in received messages queue.
+ *
+ * Returns: size of DBUS data unpacked.
+ *
+ */
+static int
+g_kdbus_decode_msg (GKdbus  *kdbus,
+                    struct   kdbus_msg *msg)
+{
+  GDBusMessage *local_msg;
+  gsize local_msg_blob_size;
+  const struct kdbus_item *item;
+  int ret_size = 0;
+  static gboolean lock = FALSE;
+
+  KDBUS_PART_FOREACH(item, msg, items)
+    {
+      if (item->size <= KDBUS_PART_HEADER_SIZE)
+        {
+          g_error(" KDBUS_DEBUG: (%s()): %llu bytes - invalid data record\n",
+                  __FUNCTION__,
+                  item->size);
+          break;
+        }
+
+      switch (item->type)
+        {
+
+        case KDBUS_MSG_PAYLOAD_OFF:
+
+          if (!lock)
+            {
+              kdbus->priv->msg_buffer_ptr = kdbus->priv->buffer_ptr + item->vec.offset;
+              lock=TRUE;
+            }
+          ret_size += item->vec.size;
+
+#ifdef KDBUS_DEBUG
+          g_print(" KDBUS_DEBUG: (%s()): KDBUS_MSG_PAYLOAD: %llu bytes, off=%llu, size=%llu\n",
+                  __FUNCTION__, item->size,
+                  (unsigned long long)item->vec.offset,
+                  (unsigned long long)item->vec.size);
+#endif
+          break;
+
+        case KDBUS_MSG_PAYLOAD_MEMFD:
+          kdbus->priv->msg_buffer_ptr = mmap(NULL, item->memfd.size, PROT_READ , MAP_SHARED, item->memfd.fd, 0);
+          if (kdbus->priv->msg_buffer_ptr == MAP_FAILED)
+            {
+              g_error(" KDBUS_DEBUG: (%s()): mmap KDBUS_MSG_PAYLOAD_MEMFD failed\n",__FUNCTION__);
+              return -1;
+            }
+
+          ret_size = item->memfd.size;
+
+#ifdef KDBUS_DEBUG
+          g_print(" KDBUS_DEBUG: (%s()): KDBUS_MSG_PAYLOAD_MEMFD: %llu bytes, size=%llu\n",
+                  __FUNCTION__,
+                  item->size,
+                  (unsigned long long)item->memfd.size);
+#endif
+          break;
+
+        case KDBUS_MSG_REPLY_TIMEOUT:
+
+#ifdef KDBUS_DEBUG
+          g_print(" KDBUS_DEBUG: (%s()): KDBUS_MSG_REPLY_TIMEOUT: %llu bytes, cookie=%llu\n",__FUNCTION__,item->size, msg->cookie_reply);
+#endif
+
+          local_msg = g_kdbus_generate_local_dbus_msg (NULL,
+                                                       G_DBUS_MESSAGE_TYPE_ERROR,
+                                                       G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED,
+                                                       g_variant_new ("(s)","Reply timeout"),
+                                                       "org.freedesktop.DBus.Error.NoReply");
+          kdbus->priv->msg_buffer_ptr = (char*)g_dbus_message_to_blob (local_msg, &local_msg_blob_size, 0, NULL);
+          ret_size = local_msg_blob_size;
+          break;
+
+        case KDBUS_MSG_REPLY_DEAD:
+
+#ifdef KDBUS_DEBUG
+          g_print(" KDBUS_DEBUG: (%s()): KDBUS_MSG_REPLY_DEAD: %llu bytes, cookie=%llu\n",__FUNCTION__,item->size, msg->cookie_reply);
+#endif
+
+          local_msg = g_kdbus_generate_local_dbus_msg (NULL,
+                                                       G_DBUS_MESSAGE_TYPE_ERROR,
+                                                       G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED,
+                                                       g_variant_new ("(s)","Name has no owner"),
+                                                       "org.freedesktop.DBus.Error.NameHasNoOwner");
+          kdbus->priv->msg_buffer_ptr = (char*)g_dbus_message_to_blob (local_msg, &local_msg_blob_size, 0, NULL);
+          ret_size = local_msg_blob_size;
+          break;
+        }
+    }
+
+  lock = FALSE;
+  return ret_size;
+}
+
+typedef struct {
+  GSource       source;
+  GPollFD       pollfd;
+  GKdbus       *kdbus;
+  GIOCondition  condition;
+  GCancellable *cancellable;
+  GPollFD       cancel_pollfd;
+  gint64        timeout_time;
+} GKdbusSource;
+
+/*
+ * kdbus_source_prepare:
+ *
+ */
+static gboolean
+kdbus_source_prepare (GSource  *source,
+                      gint     *timeout)
+{
+  GKdbusSource *kdbus_source = (GKdbusSource *)source;
+
+  if (g_cancellable_is_cancelled (kdbus_source->cancellable))
+    return TRUE;
+
+  if (kdbus_source->timeout_time)
+    {
+      gint64 now;
+
+      now = g_source_get_time (source);
+
+      *timeout = (kdbus_source->timeout_time - now + 999) / 1000;
+      if (*timeout < 0)
+        {
+          kdbus_source->kdbus->priv->timed_out = TRUE;
+          *timeout = 0;
+          return TRUE;
+        }
+    }
+  else
+    *timeout = -1;
+
+  if ((kdbus_source->condition & kdbus_source->pollfd.revents) != 0)
+    return TRUE;
+
+  return FALSE;
+}
+
+/*
+ * kdbus_source_check:
+ *
+ */
+static gboolean
+kdbus_source_check (GSource *source)
+{
+  int timeout;
+
+  return kdbus_source_prepare (source, &timeout);
+}
+
+/*
+ * kdbus_source_dispatch
+ *
+ */
+static gboolean
+kdbus_source_dispatch  (GSource      *source,
+                        GSourceFunc   callback,
+                        gpointer      user_data)
+{
+  GKdbusSourceFunc func = (GKdbusSourceFunc)callback;
+  GKdbusSource *kdbus_source = (GKdbusSource *)source;
+  GKdbus *kdbus = kdbus_source->kdbus;
+  gboolean ret;
+
+  if (kdbus_source->kdbus->priv->timed_out)
+    kdbus_source->pollfd.revents |= kdbus_source->condition & (G_IO_IN | G_IO_OUT);
+
+  ret = (*func) (kdbus,
+                 kdbus_source->pollfd.revents & kdbus_source->condition,
+                 user_data);
+
+  if (kdbus->priv->timeout)
+    kdbus_source->timeout_time = g_get_monotonic_time ()
+                               + kdbus->priv->timeout * 1000000;
+
+  else
+    kdbus_source->timeout_time = 0;
+
+  return ret;
+}
+
+/*
+ * kdbus_source_finalize
+ *
+ */
+static void
+kdbus_source_finalize (GSource *source)
+{
+  GKdbusSource *kdbus_source = (GKdbusSource *)source;
+  GKdbus *kdbus;
+
+  kdbus = kdbus_source->kdbus;
+
+  g_object_unref (kdbus);
+
+  if (kdbus_source->cancellable)
+    {
+      g_cancellable_release_fd (kdbus_source->cancellable);
+      g_object_unref (kdbus_source->cancellable);
+    }
+}
+
+/*
+ * kdbus_source_closure_callback:
+ *
+ */
+static gboolean
+kdbus_source_closure_callback (GKdbus        *kdbus,
+                               GIOCondition   condition,
+                               gpointer       data)
+{
+  GClosure *closure = data;
+  GValue params[2] = { G_VALUE_INIT, G_VALUE_INIT };
+  GValue result_value = G_VALUE_INIT;
+  gboolean result;
+
+  g_value_init (&result_value, G_TYPE_BOOLEAN);
+
+  g_value_init (&params[0], G_TYPE_KDBUS);
+  g_value_set_object (&params[0], kdbus);
+  g_value_init (&params[1], G_TYPE_IO_CONDITION);
+  g_value_set_flags (&params[1], condition);
+
+  g_closure_invoke (closure, &result_value, 2, params, NULL);
+
+  result = g_value_get_boolean (&result_value);
+  g_value_unset (&result_value);
+  g_value_unset (&params[0]);
+  g_value_unset (&params[1]);
+
+  return result;
+}
+
+static GSourceFuncs kdbus_source_funcs =
+{
+  kdbus_source_prepare,
+  kdbus_source_check,
+  kdbus_source_dispatch,
+  kdbus_source_finalize,
+  (GSourceFunc)kdbus_source_closure_callback,
+};
+
+/*
+ * kdbus_source_new:
+ *
+ */
+static GSource *
+kdbus_source_new (GKdbus        *kdbus,
+                  GIOCondition   condition,
+                  GCancellable  *cancellable)
+{
+  GSource *source;
+  GKdbusSource *kdbus_source;
+
+  source = g_source_new (&kdbus_source_funcs, sizeof (GKdbusSource));
+  g_source_set_name (source, "GKdbus");
+  kdbus_source = (GKdbusSource *)source;
+
+  kdbus_source->kdbus = g_object_ref (kdbus);
+  kdbus_source->condition = condition;
+
+  if (g_cancellable_make_pollfd (cancellable,
+                                 &kdbus_source->cancel_pollfd))
+    {
+      kdbus_source->cancellable = g_object_ref (cancellable);
+      g_source_add_poll (source, &kdbus_source->cancel_pollfd);
+    }
+
+  kdbus_source->pollfd.fd = kdbus->priv->fd;
+  kdbus_source->pollfd.events = condition;
+  kdbus_source->pollfd.revents = 0;
+  g_source_add_poll (source, &kdbus_source->pollfd);
+
+  if (kdbus->priv->timeout)
+    kdbus_source->timeout_time = g_get_monotonic_time ()
+                               + kdbus->priv->timeout * 1000000;
+  else
+    kdbus_source->timeout_time = 0;
+
+  return source;
+}
+
+/*
+ * g_kdbus_create_source:
+ *
+ */
+GSource *
+g_kdbus_create_source (GKdbus        *kdbus,
+                       GIOCondition   condition,
+                       GCancellable  *cancellable)
+{
+  g_return_val_if_fail (G_IS_KDBUS (kdbus) && (cancellable == NULL || G_IS_CANCELLABLE (cancellable)), NULL);
+
+  return kdbus_source_new (kdbus, condition, cancellable);
+}
+
+/**
+ * g_kdbus_receive:
+ * @kdbus: a #GKdbus.
+ * @cancellable: (allow-none): a %GCancellable or %NULL.
+ * @error: #GError for error reporting, or %NULL to ignore.
+ *
+ * Initiates receiving data from Kdbus.
+ * Memory offset of Kdbus message is returned by KDBUS_CMD_MSG_RECV ioctl.
+ * Memory occupied by KDBUS message is released only after DBUS message is constructed.
+ *
+ * Returns: Size of DBUS data encapsulated.
+ */
+gssize
+g_kdbus_receive (GKdbus        *kdbus,
+                 GCancellable  *cancellable,
+                 GError       **error)
+{
+  struct kdbus_msg *msg;
+
+  if (g_cancellable_set_error_if_cancelled (cancellable, error))
+    return -1;
+
+  /* get memory offset of msg */
+  again:
+    if (ioctl(kdbus->priv->fd, KDBUS_CMD_MSG_RECV, &kdbus->priv->offset) < 0)
+      {
+        if (errno == EINTR)
+          goto again;
+
+        g_error (" KDBUS_DEBUG: (%s()): ioctl MSG_RECV failed! %d (%m)\n",__FUNCTION__,errno);
+        g_set_error (error, G_IO_ERROR, g_io_error_from_errno(errno),_("Error receiving message - KDBUS_CMD_MSG_RECV error"));
+        return -1;
+      }
+
+    msg = (struct kdbus_msg *)((char*)kdbus->priv->buffer_ptr + kdbus->priv->offset);
+
+    return (g_kdbus_decode_msg(kdbus, msg));
+}
+
+/**
+ * g_kdbus_release_msg:
+ * @kdbus: a #GKdbus.
+ *
+ * Release memory occupied by kdbus_msg. Use after DBUS message is extracted.
+ *
+ */
+void
+g_kdbus_release_kmsg (GKdbus    *kdbus)
+{
+  again:
+  if (ioctl(kdbus->priv->fd, KDBUS_CMD_MSG_RELEASE, &kdbus->priv->offset) < 0)
+    {
+      if (errno == EINTR)
+        goto again;
+
+      g_error (" KDBUS_DEBUG: (%s()): ioctl MSG_RELEASE failed!\n",__FUNCTION__);
+    }
+}
+
+/*
+ * g_kdbus_get_buffer_ptr:
+ *
+ */
+gchar *
+g_kdbus_get_msg_buffer_ptr (GKdbus  *kdbus)
+{
+  g_return_val_if_fail (G_IS_KDBUS (kdbus), NULL);
+
+  return kdbus->priv->msg_buffer_ptr;
+}
+
+/**
+ * g_kdbus_send_message:
+ * @worker: object used to send/receive msgs
+ * @kdbus: a #GKdbus.
+ * @dbus_msg: DBUS message to be sent
+ * @blob: data of DBUS message to be sent
+ * @blob_size: size of data to be sent
+ * @cancellable: (allow-none): a %GCancellable or %NULL.
+ * @error: #GError for error reporting, or %NULL to ignore.
+ *
+ * DBUS message blob, header and body, is inserted in Kdbus message items.
+ * These items can be vector or memfd, depending on size of data.
+ * For large data over MEMFD_SIZE_THRESHOLD memfd is used.
+ * Using memfd requires sealing data to ensure protection from modifications.
+ *
+ * If it is first message being sent, registration on Kdbus bus is performed.
+ *
+ * Returns: size of data sent or -1 when error
+ */
+gssize
+g_kdbus_send_message (GDBusWorker   *worker,
+                      GKdbus        *kdbus,
+                      GDBusMessage  *dbus_msg,
+                      gchar         *blob,
+                      gsize          blob_size,
+                      GCancellable  *cancellable,
+                      GError       **error)
+{
+  struct kdbus_msg* kmsg;
+  struct kdbus_item *item;
+  guint64 kmsg_size = 0;
+  const gchar *name;
+  guint64 dst_id = KDBUS_DST_ID_BROADCAST;
+  gboolean use_memfd = FALSE;
+
+  if (g_cancellable_set_error_if_cancelled (cancellable, error))
+    return -1;
+
+  if (kdbus->priv->registered == FALSE)
+    {
+      if (!g_kdbus_register(kdbus))
+        {
+          g_error (" KDBUS_DEBUG: (%s()): registering failed!\n",__FUNCTION__);
+          g_set_error (error, G_IO_ERROR, g_io_error_from_errno(errno),_("Error sending message - registering failed"));
+          return -1;
+        }
+
+      if (g_strcmp0(g_dbus_message_get_member(dbus_msg), "Hello") == 0)
+        {
+          GDBusMessage *reply;
+          GString *unique_name;
+
+          #ifdef KDBUS_DEBUG
+          g_print (" KDBUS_DEBUG: (%s()): sending \"Hello\" message!\n",__FUNCTION__);
+          #endif
+
+          unique_name = g_string_new(NULL);
+          g_string_printf (unique_name,":1.%d",kdbus->priv->peer_id);
+
+          reply = g_kdbus_generate_local_dbus_msg (dbus_msg,
+                                                   G_DBUS_MESSAGE_TYPE_METHOD_RETURN,
+                                                   G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED,
+                                                   g_variant_new ("(s)",unique_name->str),
+                                                   NULL);
+          _g_dbus_worker_queue_or_deliver_received_message (worker, reply);
+
+          return blob_size;
+        }
+    }
+
+  if ((name = g_dbus_message_get_destination(dbus_msg)))
+    {
+      dst_id = KDBUS_DST_ID_WELL_KNOWN_NAME;
+      if ((name[0] == ':') && (name[1] == '1') && (name[2] == '.'))
+        {
+          dst_id = strtoull(&name[3], NULL, 10);
+          name=NULL;
+        }
+    }
+
+  if ((blob_size > MEMFD_SIZE_THRESHOLD) && (dst_id != KDBUS_DST_ID_BROADCAST))
+    {
+      use_memfd = TRUE;
+      if (g_kdbus_init_memfd(kdbus) < 0)
+        return -1;
+    }
+
+  kmsg_size = sizeof(struct kdbus_msg);
+
+  if (use_memfd)
+    /* memfd container for blob */
+    kmsg_size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_memfd));
+  else
+    /* vector for blob */
+    kmsg_size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
+
+  if (name)
+        kmsg_size += KDBUS_ITEM_SIZE(strlen(name) + 1);
+  else if (dst_id == KDBUS_DST_ID_BROADCAST)
+        kmsg_size += KDBUS_PART_HEADER_SIZE + kdbus->priv->bloom_size;
+
+  kmsg = malloc(kmsg_size);
+  if (!kmsg)
+    {
+      g_error (" KDBUS_DEBUG: (%s()): kmsg malloc error\n",__FUNCTION__);
+      g_set_error (error, G_IO_ERROR, g_io_error_from_errno(errno),_("Error sending message - kmsg malloc error"));
+      return -1;
+    }
+
+  memset(kmsg, 0, kmsg_size);
+  kmsg->size = kmsg_size;
+  kmsg->payload_type = KDBUS_PAYLOAD_DBUS1;
+  kmsg->dst_id = name ? 0 : dst_id;
+  kmsg->src_id = kdbus->priv->peer_id;
+  kmsg->cookie = g_dbus_message_get_serial(dbus_msg);
+
+  if ((g_dbus_message_get_flags (dbus_msg)) & (1<<1))
+    kmsg->flags |= KDBUS_MSG_FLAGS_NO_AUTO_START;
+
+#ifdef KDBUS_DEBUG
+  g_print (" KDBUS_DEBUG: (%s()): destination name: %s\n",__FUNCTION__,name);
+  g_print (" KDBUS_DEBUG: (%s()): blob size: %d\n",__FUNCTION__,(gint)blob_size);
+  g_print (" KDBUS_DEBUG: (%s()): serial: %llu\n",__FUNCTION__,kmsg->cookie);
+  g_print (" KDBUS_DEBUG: (%s()): src_id/peer_id: %i\n",__FUNCTION__,kdbus->priv->peer_id);
+#endif
+
+  /* build message contents */
+  item = kmsg->items;
+
+  if (use_memfd)
+    {
+      /* write blob to memfd special file */
+      if (write(kdbus->priv->memfd,blob,blob_size) != blob_size)
+        {
+          g_error (" KDBUS_DEBUG: (%s()): wirte memfd error\n",__FUNCTION__);
+          g_set_error (error, G_IO_ERROR, g_io_error_from_errno(errno),_("Error sending message - write memfd error"));
+          blob_size = -1;
+          goto out;
+        }
+
+      /* seal data - kdbus module requires it */
+      if(ioctl(kdbus->priv->memfd, KDBUS_CMD_MEMFD_SEAL_SET, 1) < 0)
+        {
+          g_print (" KDBUS_DEBUG: (%s()): KDBUS_CMD_MEMFD_SEAL_SET 1 failed\n",__FUNCTION__);
+          g_set_error (error, G_IO_ERROR, g_io_error_from_errno(errno),_("Error sending message - memfd seal set error"));
+          blob_size = -1;
+          goto out;
+        }
+
+      item->type = KDBUS_MSG_PAYLOAD_MEMFD;
+      item->size = KDBUS_PART_HEADER_SIZE + sizeof(struct kdbus_memfd);
+      item->memfd.size = blob_size;
+      item->memfd.fd = kdbus->priv->memfd;
+    }
+  else
+    {
+      MSG_ITEM_BUILD_VEC(blob, blob_size);
+    }
+
+  if (name)
+    {
+      item = KDBUS_PART_NEXT(item);
+      item->type = KDBUS_MSG_DST_NAME;
+      item->size = KDBUS_PART_HEADER_SIZE + strlen(name) + 1;
+      strcpy(item->str, name);
+    }
+  else if (dst_id == KDBUS_DST_ID_BROADCAST)
+    {
+      item = KDBUS_PART_NEXT(item);
+      item->type = KDBUS_MSG_BLOOM;
+      item->size = KDBUS_PART_HEADER_SIZE + kdbus->priv->bloom_size;
+      strncpy((gchar*)item->data,g_dbus_message_get_interface(dbus_msg),kdbus->priv->bloom_size);
+    }
+
+again:
+  if (ioctl(kdbus->priv->fd, KDBUS_CMD_MSG_SEND, kmsg))
+    {
+      GDBusMessage *reply;
+      GString *error_name;
+
+      error_name = g_string_new (NULL);
+
+      if(errno == EINTR)
+        goto again;
+      else if (errno == ENXIO)
+        {
+          g_string_printf (error_name, "Name %s does not exist", g_dbus_message_get_destination(dbus_msg));
+          reply = g_kdbus_generate_local_dbus_msg (dbus_msg,
+                                                   G_DBUS_MESSAGE_TYPE_ERROR,
+                                                   G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED,
+                                                   g_variant_new ("(s)",error_name->str),
+                                                   "org.freedesktop.DBus.Error.ServiceUnknown");
+          _g_dbus_worker_queue_or_deliver_received_message (worker, reply);
+          return 0;
+        }
+      else if ((errno == ESRCH) || (errno == EADDRNOTAVAIL))
+        {
+          if (kmsg->flags & KDBUS_MSG_FLAGS_NO_AUTO_START)
+            {
+              g_string_printf (error_name, "Name %s does not exist", g_dbus_message_get_destination(dbus_msg));
+              reply = g_kdbus_generate_local_dbus_msg (dbus_msg,
+                                                       G_DBUS_MESSAGE_TYPE_ERROR,
+                                                       G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED,
+                                                       g_variant_new ("(s)",error_name->str),
+                                                       "org.freedesktop.DBus.Error.ServiceUnknown");
+              _g_dbus_worker_queue_or_deliver_received_message (worker, reply);
+              return 0;
+            }
+          else
+            {
+              g_string_printf (error_name, "The name %s was not provided by any .service files", g_dbus_message_get_destination(dbus_msg));
+              reply = g_kdbus_generate_local_dbus_msg (dbus_msg,
+                                                       G_DBUS_MESSAGE_TYPE_ERROR,
+                                                       G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED,
+                                                       g_variant_new ("(s)",error_name->str),
+                                                       "org.freedesktop.DBus.Error.ServiceUnknown");
+              _g_dbus_worker_queue_or_deliver_received_message (worker, reply);
+              return 0;
+            }
+        }
+
+      g_error (" KDBUS_DEBUG: (%s()): ioctl error sending kdbus message:%d (%m)\n",__FUNCTION__,errno);
+      g_set_error (error, G_IO_ERROR, g_io_error_from_errno(errno), _("Error sending message - KDBUS_CMD_MSG_SEND error"));
+      return -1;
+    }
+
+#ifdef KDBUS_DEBUG
+  g_print (" KDBUS_DEBUG: (%s()): ioctl(CMD_MSG_SEND) sent successfully\n",__FUNCTION__);
+#endif
+
+out:
+  if (kdbus->priv->memfd)
+    close(kdbus->priv->memfd);
+  free(kmsg);
+  return blob_size;
+}
diff --git a/gio/gkdbus.h b/gio/gkdbus.h
new file mode 100644
index 0000000..bd16e89
--- /dev/null
+++ b/gio/gkdbus.h
@@ -0,0 +1,113 @@
+/*  GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright © 2013 Samsung Electronics
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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.
+ *
+ * Author: Michal Eljasiewicz   <m.eljasiewic at samsung.com>
+ * Author: Lukasz Skalski       <l.skalski at partner.samsung.com>
+ */
+
+#ifndef __G_KDBUS_H__
+#define __G_KDBUS_H__
+
+#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
+#error "Only <gio/gio.h> can be included directly."
+#endif
+
+#include <gio/giotypes.h>
+#include "gdbusprivate.h"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_KDBUS                                       (g_kdbus_get_type ())
+#define G_KDBUS(inst)                                      (G_TYPE_CHECK_INSTANCE_CAST ((inst),                     \
+                                                             G_TYPE_KDBUS, GKdbus))
+#define G_KDBUS_CLASS(class)                               (G_TYPE_CHECK_CLASS_CAST ((class),                       \
+                                                             G_TYPE_KDBUS, GKdbusClass))
+#define G_IS_KDBUS(inst)                                   (G_TYPE_CHECK_INSTANCE_TYPE ((inst),                     \
+                                                             G_TYPE_KDBUS))
+#define G_IS_KDBUS_CLASS(class)                            (G_TYPE_CHECK_CLASS_TYPE ((class),                       \
+                                                             G_TYPE_KDBUS))
+#define G_KDBUS_GET_CLASS(inst)                            (G_TYPE_INSTANCE_GET_CLASS ((inst),                      \
+                                                             G_TYPE_KDBUS, GKdbusClass))
+
+typedef struct _GKdbusPrivate                              GKdbusPrivate;
+typedef struct _GKdbusClass                                GKdbusClass;
+
+struct _GKdbusClass
+{
+  GObjectClass parent_class;
+
+  /*< private >*/
+
+  /* Padding for future expansion */
+  void (*_g_reserved1) (void);
+  void (*_g_reserved2) (void);
+  void (*_g_reserved3) (void);
+  void (*_g_reserved4) (void);
+  void (*_g_reserved5) (void);
+  void (*_g_reserved6) (void);
+  void (*_g_reserved7) (void);
+  void (*_g_reserved8) (void);
+  void (*_g_reserved9) (void);
+  void (*_g_reserved10) (void);
+};
+
+struct _GKdbus
+{
+  GObject parent_instance;
+  GKdbusPrivate *priv;
+};
+
+GLIB_AVAILABLE_IN_ALL
+GType                                   g_kdbus_get_type                (void) G_GNUC_CONST;
+GLIB_AVAILABLE_IN_ALL
+gboolean                                g_kdbus_open                    (GKdbus *kdbus,
+                                                                         const gchar *address,
+                                                                         GCancellable *cancellable,
+                                                                         GError **error);
+GLIB_AVAILABLE_IN_ALL
+gboolean                                g_kdbus_close                   (GKdbus *kdbus,
+                                                                         GError **error);
+GLIB_AVAILABLE_IN_ALL
+gboolean                                g_kdbus_is_closed               (GKdbus *kdbus);
+GLIB_AVAILABLE_IN_ALL
+gssize                                  g_kdbus_receive                 (GKdbus *kdbus,
+                                                                         GCancellable *cancellable,
+                                                                         GError **error);
+GLIB_AVAILABLE_IN_ALL
+gssize                                  g_kdbus_send_message            (GDBusWorker *worker,
+                                                                         GKdbus *kdbus,
+                                                                         GDBusMessage *dbus_msg,
+                                                                         gchar *blob,
+                                                                         gsize blob_size,
+                                                                         GCancellable *cancellable,
+                                                                         GError **error);
+GLIB_AVAILABLE_IN_ALL
+gboolean                                g_kdbus_register                (GKdbus *kdbus);
+GLIB_AVAILABLE_IN_ALL
+GSource *                               g_kdbus_create_source           (GKdbus *kdbus,
+                                                                         GIOCondition condition,
+                                                                         GCancellable *cancellable);
+GLIB_AVAILABLE_IN_ALL
+void                                    g_kdbus_release_kmsg            (GKdbus *kdbus);
+GLIB_AVAILABLE_IN_ALL
+gchar *                                 g_kdbus_get_msg_buffer_ptr      (GKdbus *kdbus);
+
+G_END_DECLS
+
+#endif /* __G_KDBUS_H__ */
diff --git a/gio/gkdbusconnection.c b/gio/gkdbusconnection.c
new file mode 100644
index 0000000..9c6c150
--- /dev/null
+++ b/gio/gkdbusconnection.c
@@ -0,0 +1,196 @@
+/*  GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright © 2013 Samsung Electronics
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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.
+ *
+ * Author: Michal Eljasiewicz   <m.eljasiewic at samsung.com>
+ * Author: Lukasz Skalski       <l.skalski at partner.samsung.com>
+ */
+
+#include <fcntl.h>
+#include "config.h"
+
+#include <gio/gtask.h>
+
+#include "gkdbusconnection.h"
+#include "gunixconnection.h"
+
+
+/**
+ * SECTION:gkdbusconnection
+ * @short_description: A kdbus connection
+ * @include: gio/gio.h
+ * @see_also: #GIOStream, #GKdbusClient
+ *
+ * #GKdbusConnection is a #GIOStream for a connected kdbus bus.
+ */
+
+G_DEFINE_TYPE (GKdbusConnection, g_kdbus_connection, G_TYPE_IO_STREAM);
+
+struct _GKdbusConnectionPrivate
+{
+  GKdbus        *kdbus;
+  gboolean       in_dispose;
+};
+
+/*
+ * g_kdbus_connection_new:
+ */
+GKdbusConnection *
+g_kdbus_connection_new (void)
+{
+  return g_object_new(G_TYPE_KDBUS_CONNECTION,NULL);
+}
+
+/*
+ * g_kdbus_connection_connect:
+ */
+gboolean
+g_kdbus_connection_connect (GKdbusConnection  *connection,
+                            const gchar       *address,
+                            GCancellable      *cancellable,
+                            GError           **error)
+{
+  g_return_val_if_fail (G_IS_KDBUS_CONNECTION (connection), FALSE);
+
+  return g_kdbus_open (connection->priv->kdbus,address,cancellable,error);
+}
+
+/*
+ * g_kdbus_connection_is_connected:
+ */
+gboolean
+g_kdbus_connection_is_connected (GKdbusConnection  *connection)
+{
+  return (!g_kdbus_is_closed (connection->priv->kdbus));
+}
+
+/*
+ * g_kdbus_connection_get_property:
+ */
+static void
+g_kdbus_connection_get_property (GObject     *object,
+                                 guint        prop_id,
+                                 GValue      *value,
+                                 GParamSpec  *pspec)
+{
+  //GKdbusConnection *connection = G_KDBUS_CONNECTION (object);
+  switch (prop_id)
+    {
+      default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+/*
+ * g_kdbus_connection_set_property
+ */
+static void
+g_kdbus_connection_set_property (GObject       *object,
+                                 guint          prop_id,
+                                 const GValue  *value,
+                                 GParamSpec    *pspec)
+{
+  // GKdbusConnection *connection = G_KDBUS_CONNECTION (object);
+  switch (prop_id)
+    {
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+/* g_kdbus_connection_dispsose:
+ *
+ * TODO
+ */
+static void
+g_kdbus_connection_dispose (GObject *object)
+{
+  GKdbusConnection *connection = G_KDBUS_CONNECTION (object);
+
+  connection->priv->in_dispose = TRUE;
+
+  G_OBJECT_CLASS (g_kdbus_connection_parent_class)->dispose (object);
+
+  connection->priv->in_dispose = FALSE;
+}
+
+/*
+ * g_kdbus_connection_finalize:
+ */
+static void
+g_kdbus_connection_finalize (GObject *object)
+{
+  //GKdbusConnection *connection = G_KDBUS_CONNECTION (object);
+  G_OBJECT_CLASS (g_kdbus_connection_parent_class)->finalize (object);
+}
+
+/*
+ * g_kdbus_connection_close:
+ */
+gboolean
+g_kdbus_connection_close (GIOStream     *stream,
+                          GCancellable  *cancellable,
+                          GError       **error)
+{
+  GKdbusConnection *connection = G_KDBUS_CONNECTION (stream);
+
+  if (connection->priv->in_dispose)
+    return TRUE;
+
+  return g_kdbus_close (connection->priv->kdbus, error);
+  return TRUE;
+}
+
+/*
+ * g_kdbus_connection_class_init:
+ */
+static void
+g_kdbus_connection_class_init (GKdbusConnectionClass  *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (GKdbusConnectionPrivate));
+
+  gobject_class->set_property = g_kdbus_connection_set_property;
+  gobject_class->get_property = g_kdbus_connection_get_property;
+  gobject_class->finalize = g_kdbus_connection_finalize;
+  gobject_class->dispose = g_kdbus_connection_dispose;
+}
+
+/*
+ * g_kdbus_connection_init:
+ */
+static void
+g_kdbus_connection_init (GKdbusConnection  *connection)
+{
+  connection->priv = G_TYPE_INSTANCE_GET_PRIVATE (connection,
+                                                  G_TYPE_KDBUS_CONNECTION,
+                                                  GKdbusConnectionPrivate);
+  connection->priv->kdbus = g_object_new(G_TYPE_KDBUS,NULL);
+}
+
+/*
+ * g_kdbus_connection_get_kdbus: gets the underlying #GKdbus object of the connection.
+ */
+GKdbus *
+g_kdbus_connection_get_kdbus (GKdbusConnection *connection)
+{
+  g_return_val_if_fail (G_IS_KDBUS_CONNECTION (connection), NULL);
+
+  return connection->priv->kdbus;
+}
diff --git a/gio/gkdbusconnection.h b/gio/gkdbusconnection.h
new file mode 100644
index 0000000..8a229dc
--- /dev/null
+++ b/gio/gkdbusconnection.h
@@ -0,0 +1,91 @@
+/*  GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright © 2013 Samsung Electronics
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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.
+ *
+ * Author: Michal Eljasiewicz   <m.eljasiewic at samsung.com>
+ * Author: Lukasz Skalski       <l.skalski at partner.samsung.com>
+ */
+
+#ifndef __G_KDBUS_CONNECTION_H__
+#define __G_KDBUS_CONNECTION_H__
+
+#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
+#error "Only <gio/gio.h> can be included directly."
+#endif
+
+#include <glib-object.h>
+#include <gio/gkdbus.h>
+#include <gio/giostream.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_KDBUS_CONNECTION                            (g_kdbus_connection_get_type ())
+#define G_KDBUS_CONNECTION(inst)                           (G_TYPE_CHECK_INSTANCE_CAST ((inst),                     \
+                                                            G_TYPE_KDBUS_CONNECTION, GKdbusConnection))
+#define G_KDBUS_CONNECTION_CLASS(class)                    (G_TYPE_CHECK_CLASS_CAST ((class),                       \
+                                                            G_TYPE_KDBUS_CONNECTION, GKdbusConnectionClass))
+#define G_IS_KDBUS_CONNECTION(inst)                        (G_TYPE_CHECK_INSTANCE_TYPE ((inst),                     \
+                                                            G_TYPE_KDBUS_CONNECTION))
+#define G_IS_KDBUS_CONNECTION_CLASS(class)                 (G_TYPE_CHECK_CLASS_TYPE ((class),                       \
+                                                            G_TYPE_KDBUS_CONNECTION))
+#define G_KDBUS_CONNECTION_GET_CLASS(inst)                 (G_TYPE_INSTANCE_GET_CLASS ((inst),                      \
+                                                            G_TYPE_KDBUS_CONNECTION, GKdbusConnectionClass))
+
+typedef struct _GKdbusConnectionPrivate                    GKdbusConnectionPrivate;
+typedef struct _GKdbusConnectionClass                      GKdbusConnectionClass;
+
+struct _GKdbusConnectionClass
+{
+  GIOStreamClass parent_class;
+
+  /* Padding for future expansion */
+  void (*_g_reserved1) (void);
+  void (*_g_reserved2) (void);
+  void (*_g_reserved3) (void);
+  void (*_g_reserved4) (void);
+  void (*_g_reserved5) (void);
+  void (*_g_reserved6) (void);
+};
+
+struct _GKdbusConnection
+{
+  GIOStream parent_instance;
+  GKdbusConnectionPrivate *priv;
+};
+
+GLIB_AVAILABLE_IN_ALL
+GType              g_kdbus_connection_get_type                  (void) G_GNUC_CONST;
+GLIB_AVAILABLE_IN_ALL
+GKdbusConnection  *g_kdbus_connection_new                       (void);
+GLIB_AVAILABLE_IN_ALL
+gboolean           g_kdbus_connection_is_connected              (GKdbusConnection        *connection);
+GLIB_AVAILABLE_IN_ALL
+gboolean           g_kdbus_connection_connect                   (GKdbusConnection        *connection,
+                                                                 const gchar             *address,
+                                                                 GCancellable            *cancellable,
+                                                                 GError                 **error);
+GLIB_AVAILABLE_IN_ALL
+gboolean           g_kdbus_connection_close                     (GIOStream               *stream,
+                                                                 GCancellable            *cancellable,
+                                                                 GError                 **error);
+GLIB_AVAILABLE_IN_ALL
+GKdbus            *g_kdbus_connection_get_kdbus                 (GKdbusConnection        *connection);
+
+G_END_DECLS
+
+#endif /* __G_KDBUS_CONNECTION_H__ */
-- 
1.8.4.rc3



More information about the systemd-devel mailing list