1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright © 2013 Samsung
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Authors: Michal Eljasiewicz <m.eljasiewic@samsung.com>
21 * Authors: Lukasz Skalski <l.skalski@partner.samsung.com>
27 #include "glib-unix.h"
37 #ifdef HAVE_SYS_FILIO_H
38 # include <sys/filio.h>
45 #include "gcancellable.h"
46 #include "gioenumtypes.h"
47 #include "ginitable.h"
53 #include "gdbusmessage.h"
54 #include "gdbusconnection.h"
56 #define KDBUS_PART_FOREACH(part, head, first) \
57 for (part = (head)->first; \
58 (guint8 *)(part) < (guint8 *)(head) + (head)->size; \
59 part = KDBUS_PART_NEXT(part))
60 #define RECEIVE_POOL_SIZE (10 * 1024LU * 1024LU)
62 #define MSG_ITEM_BUILD_VEC(data, datasize) \
63 item->type = KDBUS_MSG_PAYLOAD_VEC; \
64 item->size = KDBUS_PART_HEADER_SIZE + sizeof(struct kdbus_vec); \
65 item->vec.address = (unsigned long) data; \
66 item->vec.size = datasize;
68 #define KDBUS_ALIGN8(l) (((l) + 7) & ~7)
69 #define KDBUS_PART_NEXT(part) \
70 (typeof(part))(((guint8 *)part) + KDBUS_ALIGN8((part)->size))
71 #define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8((s) + KDBUS_PART_HEADER_SIZE)
75 * @short_description: Low-level kdbus object
77 * @see_also: #GInitable, <link linkend="gio-gnetworking.h">gnetworking.h</link>
81 static void g_kdbus_initable_iface_init (GInitableIface *iface);
82 static gboolean g_kdbus_initable_init (GInitable *initable,
83 GCancellable *cancellable,
86 G_DEFINE_TYPE_WITH_CODE (GKdbus, g_kdbus, G_TYPE_OBJECT,
87 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
88 g_kdbus_initable_iface_init));
103 g_kdbus_get_property (GObject *object,
108 //GKdbus *kdbus = G_KDBUS (object);
113 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
119 g_kdbus_set_property (GObject *object,
124 //GKdbus *kdbus = G_KDBUS (object);
129 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
135 g_kdbus_finalize (GObject *object)
137 //GKdbus *kdbus = G_KDBUS (object);
139 // TODO: Posprzatac po obiekcie
144 g_kdbus_class_init (GKdbusClass *klass)
146 GObjectClass *gobject_class G_GNUC_UNUSED = G_OBJECT_CLASS (klass);
148 g_type_class_add_private (klass, sizeof (GKdbusPrivate));
150 gobject_class->finalize = g_kdbus_finalize;
151 gobject_class->set_property = g_kdbus_set_property;
152 gobject_class->get_property = g_kdbus_get_property;
156 g_kdbus_initable_iface_init (GInitableIface *iface)
158 iface->init = g_kdbus_initable_init;
162 g_kdbus_init (GKdbus *kdbus)
164 kdbus->priv = G_TYPE_INSTANCE_GET_PRIVATE (kdbus, G_TYPE_KDBUS, GKdbusPrivate);
165 kdbus->priv->fd = -1;
166 kdbus->priv->path = NULL;
167 kdbus->priv->buffer_ptr = NULL;
168 kdbus->priv->peer_id = -1;
169 kdbus->priv->sender = NULL;
173 g_kdbus_initable_init (GInitable *initable,
174 GCancellable *cancellable,
179 g_return_val_if_fail (G_IS_KDBUS (initable), FALSE);
181 kdbus = G_KDBUS (initable);
183 if (cancellable != NULL)
185 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
186 _("Cancellable initialization not supported"));
190 kdbus->priv->inited = TRUE;
199 * Returns: the file descriptor of the kdbus.
202 g_kdbus_get_fd (GKdbus *kdbus)
204 g_return_val_if_fail (G_IS_KDBUS (kdbus), FALSE);
206 return kdbus->priv->fd;
214 g_kdbus_open (GKdbus *kdbus,
215 const gchar *address,
216 GCancellable *cancellable,
219 g_return_val_if_fail (G_IS_KDBUS (kdbus), FALSE);
220 g_print ("ADDRESS: %s\n",address);
221 kdbus->priv->fd = open(address, O_RDWR|O_CLOEXEC|O_NONBLOCK);
222 g_print ("FD: %d\n",kdbus->priv->fd);
229 * @error: #GError for error reporting, or %NULL to ignore.
233 g_kdbus_close (GKdbus *kdbus,
238 close(kdbus->priv->fd);
240 kdbus->priv->closed = TRUE;
241 kdbus->priv->fd = -1;
250 * Checks whether a kdbus is closed.
252 * Returns: %TRUE if kdbus is closed, %FALSE otherwise
255 g_kdbus_is_closed (GKdbus *kdbus)
257 g_return_val_if_fail (G_IS_KDBUS (kdbus), FALSE);
259 return kdbus->priv->closed;
263 * Registration on Kdbus bus.
264 * Hello message + unique name + mapping memory for incoming messages.
266 * @returns #TRUE on success
268 gboolean g_kdbus_register(GKdbus *kdbus)
270 struct kdbus_cmd_hello __attribute__ ((__aligned__(8))) hello;
272 hello.conn_flags = KDBUS_HELLO_ACCEPT_FD/* |
273 KDBUS_HELLO_ATTACH_COMM |
274 KDBUS_HELLO_ATTACH_EXE |
275 KDBUS_HELLO_ATTACH_CMDLINE |
276 KDBUS_HELLO_ATTACH_CAPS |
277 KDBUS_HELLO_ATTACH_CGROUP |
278 KDBUS_HELLO_ATTACH_SECLABEL |
279 KDBUS_HELLO_ATTACH_AUDIT*/;
280 hello.size = sizeof(struct kdbus_cmd_hello);
281 hello.pool_size = RECEIVE_POOL_SIZE;
283 if (ioctl(kdbus->priv->fd, KDBUS_CMD_HELLO, &hello))
285 g_print("FD: %d Failed to send hello: %m, %d",kdbus->priv->fd,errno);
289 kdbus->priv->peer_id = hello.id;
290 g_print("-- Our peer ID is: %llu\n", hello.id);
291 // TODO (ASK RADEK)transportS->bloom_size = hello.bloom_size;
293 kdbus->priv->buffer_ptr = mmap(NULL, RECEIVE_POOL_SIZE, PROT_READ, MAP_SHARED, kdbus->priv->fd, 0);
294 if (kdbus->priv->buffer_ptr == MAP_FAILED)
296 g_print("Error when mmap: %m, %d",errno);
304 * g_kdbus_decode_msg:
305 * @kdbus_msg: kdbus message received into buffer
309 g_kdbus_decode_msg(GKdbus *kdbus,
310 struct kdbus_msg *msg,
313 const struct kdbus_item *item;
316 KDBUS_PART_FOREACH(item, msg, items)
318 if (item->size <= KDBUS_PART_HEADER_SIZE)
320 g_print(" +(%llu bytes) invalid data record\n", item->size);
321 break; //??? continue (because dbus will find error) or break
326 case KDBUS_MSG_PAYLOAD_OFF:
327 memcpy(data, (char *)kdbus->priv->buffer_ptr + item->vec.offset, item->vec.size);
328 data += item->vec.size;
329 ret_size += item->vec.size;
331 g_print(" + KDBUS_MSG_PAYLOAD (%llu bytes) off=%llu size=%llu\n", item->size,
332 (unsigned long long)item->vec.offset,
333 (unsigned long long)item->vec.size);
336 case KDBUS_MSG_REPLY_TIMEOUT:
337 g_print(" + KDBUS_MSG_REPLY_TIMEOUT (%llu bytes) cookie=%llu\n", item->size, msg->cookie_reply);
340 message = generate_local_error_message(msg->cookie_reply, DBUS_ERROR_NO_REPLY, NULL);
347 ret_size = put_message_into_data(message, data);
351 case KDBUS_MSG_REPLY_DEAD:
352 g_print(" + (%llu bytes) cookie=%llu\n", item->size, msg->cookie_reply);
355 message = generate_local_error_message(msg->cookie_reply, DBUS_ERROR_NAME_HAS_NO_OWNER, NULL);
362 ret_size = put_message_into_data(message, data);
380 g_kdbus_receive (GKdbus *kdbus,
385 guint64 __attribute__ ((__aligned__(8))) offset;
386 struct kdbus_msg *msg;
388 // get memory offset of msg
390 if (ioctl(kdbus->priv->fd, KDBUS_CMD_MSG_RECV, &offset) < 0)
397 msg = (struct kdbus_msg *)((char*)kdbus->priv->buffer_ptr + offset);
399 ret_size = g_kdbus_decode_msg(kdbus, msg, (char*)data);
401 // Release memory occupied by msg
403 if (ioctl(kdbus->priv->fd, KDBUS_CMD_MSG_RELEASE, &offset) < 0)
413 gchar* g_kdbus_get_sender(GKdbus *kdbus)
415 return kdbus->priv->sender;
419 * TODO add checks for mallocs
422 g_kdbus_send_reply(GDBusWorker *worker,
424 GDBusMessage *dbus_msg)
426 GDBusMessage *reply = NULL;
427 char *unique_name = NULL;
430 reply = g_dbus_message_new_method_reply(dbus_msg);
431 g_dbus_message_set_sender(reply, "org.freedesktop.DBus");
433 unique_name = malloc(30); // TODO should allow for Kdbus peer ID max value ?
434 sprintf(unique_name, "%i", kdbus->priv->peer_id);
436 sender = malloc (strlen(unique_name) + 4);
439 sprintf(sender, ":1.%s", unique_name);
440 kdbus->priv->sender = sender;
441 g_print ("g_kdbus_send_reply: sender set to:%s! \n", kdbus->priv->sender);
443 g_dbus_message_set_body(reply, g_variant_new ("(s)", unique_name));
444 _g_dbus_worker_queue_or_deliver_received_message (worker, reply);
450 * g_kdbus_send_message:
454 g_kdbus_send_message (GDBusWorker *worker,
456 GDBusMessage *dbus_msg,
461 struct kdbus_msg* kmsg;
462 struct kdbus_item *item;
463 guint64 kmsg_size = 0;
465 guint64 dst_id = KDBUS_DST_ID_BROADCAST;
468 // if message to org.Freedesktop.DBus then handle differently
469 if(g_strcmp0(g_dbus_message_get_member(dbus_msg), "Hello") == 0)
473 g_print ("kdbus_send_message: sending Hello message! \n");
475 if(!g_kdbus_register(kdbus))
477 g_print ("kdbus_send_message: registering failed! \n");
481 g_kdbus_send_reply(worker, kdbus, dbus_msg);
483 g_print ("kdbus_send_message: hello sent! \n");
488 g_print ("kdbus_send_message: blob_size: %i \n", (int)blob_size);
491 dst = g_dbus_message_get_destination(dbus_msg);
492 g_print ("kdbus_send_message: destination name: %s \n", dst);
494 kmsg_size = sizeof(struct kdbus_msg);
495 kmsg_size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); // vector for blob
498 kmsg_size += KDBUS_ITEM_SIZE(strlen(dst) + 1);
499 else if (dst_id == KDBUS_DST_ID_BROADCAST)
500 kmsg_size += KDBUS_PART_HEADER_SIZE + 32; /* TODO transport->bloom_size*/;
502 kmsg = malloc(kmsg_size);
509 memset(kmsg, 0, kmsg_size);
510 kmsg->size = kmsg_size;
511 kmsg->payload_type = KDBUS_PAYLOAD_DBUS1;
512 kmsg->dst_id = dst ? 0 : dst_id;
513 kmsg->src_id = kdbus->priv->peer_id;
514 kmsg->cookie = g_dbus_message_get_serial(dbus_msg);
515 g_print ("kdbus_send_message: serial: %i \n", kmsg->cookie);
516 g_print ("kdbus_send_message: src_id/peer_id: %i \n", kdbus->priv->peer_id);
518 // build message contents
521 MSG_ITEM_BUILD_VEC(blob, blob_size);
525 item = KDBUS_PART_NEXT(item);
526 item->type = KDBUS_MSG_DST_NAME;
527 item->size = KDBUS_PART_HEADER_SIZE + strlen(dst) + 1;
528 strcpy(item->str, dst);
530 else if (dst_id == KDBUS_DST_ID_BROADCAST)
532 item = KDBUS_PART_NEXT(item);
533 item->type = KDBUS_MSG_BLOOM;
534 item->size = KDBUS_PART_HEADER_SIZE + 32; /* TODO transport->bloom_size*/;
535 // TODO (ASK RADEK) strncpy(item->data, dbus_message_get_interface(message), transport->bloom_size);
539 if (ioctl(kdbus->priv->fd, KDBUS_CMD_MSG_SEND, kmsg))
544 g_warning ("g_kdbus_send_message: ioctl error sending kdbus message: %d (%m) \n", errno);
546 g_print ("kdbus_send_message: ioctl(CMD_MSG_SEND) sent successfully \n");
553 /***************************************************************************************************************
561 g_kdbus_send (GKdbus *kdbus,
564 GCancellable *cancellable,
574 * g_kdbus_receive_message:
578 g_kdbus_receive_message (Gkdbus *kdbus,
579 GkdbusAddress **address,
580 GInputVector *vectors,
582 GkdbusControlMessage ***messages,
585 GCancellable *cancellable,