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));
102 g_kdbus_get_property (GObject *object,
107 //GKdbus *kdbus = G_KDBUS (object);
112 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
118 g_kdbus_set_property (GObject *object,
123 //GKdbus *kdbus = G_KDBUS (object);
128 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
134 g_kdbus_finalize (GObject *object)
136 //GKdbus *kdbus = G_KDBUS (object);
138 // TODO: Posprzatac po obiekcie
143 g_kdbus_class_init (GKdbusClass *klass)
145 GObjectClass *gobject_class G_GNUC_UNUSED = G_OBJECT_CLASS (klass);
147 g_type_class_add_private (klass, sizeof (GKdbusPrivate));
149 gobject_class->finalize = g_kdbus_finalize;
150 gobject_class->set_property = g_kdbus_set_property;
151 gobject_class->get_property = g_kdbus_get_property;
155 g_kdbus_initable_iface_init (GInitableIface *iface)
157 iface->init = g_kdbus_initable_init;
161 g_kdbus_init (GKdbus *kdbus)
163 kdbus->priv = G_TYPE_INSTANCE_GET_PRIVATE (kdbus, G_TYPE_KDBUS, GKdbusPrivate);
164 kdbus->priv->fd = -1;
165 kdbus->priv->path = NULL;
166 kdbus->priv->buffer_ptr = NULL;
167 kdbus->priv->peer_id = -1;
171 g_kdbus_initable_init (GInitable *initable,
172 GCancellable *cancellable,
177 g_return_val_if_fail (G_IS_KDBUS (initable), FALSE);
179 kdbus = G_KDBUS (initable);
181 if (cancellable != NULL)
183 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
184 _("Cancellable initialization not supported"));
188 kdbus->priv->inited = TRUE;
197 * Returns: the file descriptor of the kdbus.
200 g_kdbus_get_fd (GKdbus *kdbus)
202 g_return_val_if_fail (G_IS_KDBUS (kdbus), FALSE);
204 return kdbus->priv->fd;
212 g_kdbus_open (GKdbus *kdbus,
213 const gchar *address,
214 GCancellable *cancellable,
217 g_return_val_if_fail (G_IS_KDBUS (kdbus), FALSE);
218 g_print ("ADDRESS: %s\n",address);
219 kdbus->priv->fd = open(address, O_RDWR|O_CLOEXEC|O_NONBLOCK);
220 g_print ("FD: %d\n",kdbus->priv->fd);
227 * @error: #GError for error reporting, or %NULL to ignore.
231 g_kdbus_close (GKdbus *kdbus,
236 close(kdbus->priv->fd);
238 kdbus->priv->closed = TRUE;
239 kdbus->priv->fd = -1;
248 * Checks whether a kdbus is closed.
250 * Returns: %TRUE if kdbus is closed, %FALSE otherwise
253 g_kdbus_is_closed (GKdbus *kdbus)
255 g_return_val_if_fail (G_IS_KDBUS (kdbus), FALSE);
257 return kdbus->priv->closed;
261 * Registration on Kdbus bus.
262 * Hello message + unique name + mapping memory for incoming messages.
264 * @returns #TRUE on success
266 gboolean g_kdbus_register(GKdbus *kdbus)
268 struct kdbus_cmd_hello __attribute__ ((__aligned__(8))) hello;
270 hello.conn_flags = KDBUS_HELLO_ACCEPT_FD/* |
271 KDBUS_HELLO_ATTACH_COMM |
272 KDBUS_HELLO_ATTACH_EXE |
273 KDBUS_HELLO_ATTACH_CMDLINE |
274 KDBUS_HELLO_ATTACH_CAPS |
275 KDBUS_HELLO_ATTACH_CGROUP |
276 KDBUS_HELLO_ATTACH_SECLABEL |
277 KDBUS_HELLO_ATTACH_AUDIT*/;
278 hello.size = sizeof(struct kdbus_cmd_hello);
279 hello.pool_size = RECEIVE_POOL_SIZE;
281 if (ioctl(kdbus->priv->fd, KDBUS_CMD_HELLO, &hello))
283 g_print("FD: %d Failed to send hello: %m, %d",kdbus->priv->fd,errno);
287 kdbus->priv->peer_id = hello.id;
288 g_print("-- Our peer ID is: %llu\n", hello.id);
289 // TODO (ASK RADEK)transportS->bloom_size = hello.bloom_size;
291 kdbus->priv->buffer_ptr = mmap(NULL, RECEIVE_POOL_SIZE, PROT_READ, MAP_SHARED, kdbus->priv->fd, 0);
292 if (kdbus->priv->buffer_ptr == MAP_FAILED)
294 g_print("Error when mmap: %m, %d",errno);
302 * g_kdbus_decode_msg:
303 * @kdbus_msg: kdbus message received into buffer
307 g_kdbus_decode_msg(GKdbus *kdbus,
308 struct kdbus_msg *msg,
311 const struct kdbus_item *item;
314 KDBUS_PART_FOREACH(item, msg, items)
316 if (item->size <= KDBUS_PART_HEADER_SIZE)
318 g_print(" +(%llu bytes) invalid data record\n", item->size);
319 break; //??? continue (because dbus will find error) or break
324 case KDBUS_MSG_PAYLOAD_OFF:
325 memcpy(data, (char *)kdbus->priv->buffer_ptr + item->vec.offset, item->vec.size);
326 data += item->vec.size;
327 ret_size += item->vec.size;
329 g_print(" + KDBUS_MSG_PAYLOAD (%llu bytes) off=%llu size=%llu\n", item->size,
330 (unsigned long long)item->vec.offset,
331 (unsigned long long)item->vec.size);
334 case KDBUS_MSG_REPLY_TIMEOUT:
335 g_print(" + KDBUS_MSG_REPLY_TIMEOUT (%llu bytes) cookie=%llu\n", item->size, msg->cookie_reply);
338 message = generate_local_error_message(msg->cookie_reply, DBUS_ERROR_NO_REPLY, NULL);
345 ret_size = put_message_into_data(message, data);
349 case KDBUS_MSG_REPLY_DEAD:
350 g_print(" + (%llu bytes) cookie=%llu\n", item->size, msg->cookie_reply);
353 message = generate_local_error_message(msg->cookie_reply, DBUS_ERROR_NAME_HAS_NO_OWNER, NULL);
360 ret_size = put_message_into_data(message, data);
378 g_kdbus_receive (GKdbus *kdbus,
383 guint64 __attribute__ ((__aligned__(8))) offset;
384 struct kdbus_msg *msg;
386 // get memory offset of msg
388 if (ioctl(kdbus->priv->fd, KDBUS_CMD_MSG_RECV, &offset) < 0)
395 msg = (struct kdbus_msg *)((char*)kdbus->priv->buffer_ptr + offset);
397 ret_size = g_kdbus_decode_msg(kdbus, msg, (char*)data);
399 // Release memory occupied by msg
401 if (ioctl(kdbus->priv->fd, KDBUS_CMD_MSG_RELEASE, &offset) < 0)
412 g_kdbus_send_reply(GDBusWorker *worker,
414 GDBusMessage *dbus_msg)
416 GDBusMessage *reply = NULL;
417 char *unique_name = NULL;
419 reply = g_dbus_message_new_method_reply(dbus_msg);
420 g_dbus_message_set_sender(reply, "org.freedesktop.DBus");
422 unique_name = malloc(30); // TODO should allow for Kdbus peer ID max value ?
423 sprintf(unique_name, "%i", kdbus->priv->peer_id);
425 g_dbus_message_set_body(reply, g_variant_new ("(s)", unique_name));
427 _g_dbus_worker_queue_or_deliver_received_message (worker, reply);
433 * g_kdbus_send_message:
437 g_kdbus_send_message (GDBusWorker *worker,
439 GDBusMessage *dbus_msg,
444 struct kdbus_msg* kmsg;
445 struct kdbus_item *item;
446 guint64 kmsg_size = 0;
448 guint64 dst_id = KDBUS_DST_ID_BROADCAST;
451 // if message to org.Freedesktop.DBus then handle differently
452 if(g_strcmp0(g_dbus_message_get_member(dbus_msg), "Hello") == 0)
456 g_print ("kdbus_send_message: sending Hello message! \n");
458 if(!g_kdbus_register(kdbus))
460 g_print ("kdbus_send_message: registering failed! \n");
464 g_kdbus_send_reply(worker, kdbus, dbus_msg);
471 g_print ("kdbus_send_message: blob_size: %i \n", (int)blob_size);
474 dst = g_dbus_message_get_destination(dbus_msg);
475 g_print ("kdbus_send_message: destination name: %s \n", dst);
477 kmsg_size = sizeof(struct kdbus_msg);
478 kmsg_size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); // vector for blob
481 kmsg_size += KDBUS_ITEM_SIZE(strlen(dst) + 1);
482 else if (dst_id == KDBUS_DST_ID_BROADCAST)
483 kmsg_size += KDBUS_PART_HEADER_SIZE + 32; /* TODO transport->bloom_size*/;
485 kmsg = malloc(kmsg_size);
492 memset(kmsg, 0, kmsg_size);
493 kmsg->size = kmsg_size;
494 kmsg->payload_type = KDBUS_PAYLOAD_DBUS1;
495 kmsg->dst_id = dst ? 0 : dst_id;
496 kmsg->src_id = strtoull(g_dbus_message_get_sender(dbus_msg), NULL , 10);
497 kmsg->cookie = g_dbus_message_get_serial(dbus_msg);
499 g_print ("kdbus_send_message unique_name/message->sender: %s \n", g_dbus_message_get_sender(dbus_msg));
501 // build message contents
504 MSG_ITEM_BUILD_VEC(blob, blob_size);
508 item = KDBUS_PART_NEXT(item);
509 item->type = KDBUS_MSG_DST_NAME;
510 item->size = KDBUS_PART_HEADER_SIZE + strlen(dst) + 1;
511 strcpy(item->str, dst);
513 else if (dst_id == KDBUS_DST_ID_BROADCAST)
515 item = KDBUS_PART_NEXT(item);
516 item->type = KDBUS_MSG_BLOOM;
517 item->size = KDBUS_PART_HEADER_SIZE + 32; /* TODO transport->bloom_size*/;
518 // TODO (ASK RADEK) strncpy(item->data, dbus_message_get_interface(message), transport->bloom_size);
522 if (ioctl(kdbus->priv->fd, KDBUS_CMD_MSG_SEND, kmsg))
527 g_warning ("g_kdbus_send_message: ioctl error sending kdbus message: %d (%m) \n", errno);
536 /***************************************************************************************************************
544 g_kdbus_send (GKdbus *kdbus,
547 GCancellable *cancellable,
557 * g_kdbus_receive_message:
561 g_kdbus_receive_message (Gkdbus *kdbus,
562 GkdbusAddress **address,
563 GInputVector *vectors,
565 GkdbusControlMessage ***messages,
568 GCancellable *cancellable,