[Sending] sender in outgoing message set.
[platform/upstream/glib.git] / gio / gkdbus.c
1 /*  GIO - GLib Input, Output and Streaming Library
2  *
3  * Copyright © 2013 Samsung
4  *
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.
9  *
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.
14  *
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.
19  *
20  * Authors: Michal Eljasiewicz <m.eljasiewic@samsung.com>
21  * Authors: Lukasz Skalski <l.skalski@partner.samsung.com>
22  */
23
24 #include "config.h"
25
26 #include "gkdbus.h"
27 #include "glib-unix.h"
28
29 #include <errno.h>
30 #include <signal.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <sys/mman.h>
35 #include <stdio.h>
36
37 #ifdef HAVE_SYS_FILIO_H
38 # include <sys/filio.h>
39 #endif
40
41 #ifdef HAVE_SYS_UIO_H
42 #include <sys/uio.h>
43 #endif
44
45 #include "gcancellable.h"
46 #include "gioenumtypes.h"
47 #include "ginitable.h"
48 #include "gioerror.h"
49 #include "gioenums.h"
50 #include "gioerror.h"
51 #include "glibintl.h"
52 #include "kdbus.h"
53 #include "gdbusmessage.h"
54 #include "gdbusconnection.h"
55
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)
61
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;
67
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)
72
73 /**
74  * SECTION:gkdbus
75  * @short_description: Low-level kdbus object
76  * @include: gio/gio.h
77  * @see_also: #GInitable, <link linkend="gio-gnetworking.h">gnetworking.h</link>
78  *
79  */
80
81 static void     g_kdbus_initable_iface_init (GInitableIface  *iface);
82 static gboolean g_kdbus_initable_init       (GInitable       *initable,
83                                               GCancellable    *cancellable,
84                                               GError         **error);
85
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));
89
90 struct _GKdbusPrivate
91 {
92   gchar          *path;
93   gint            fd;
94   guint           closed : 1;
95   guint           inited : 1;
96   gchar          *buffer_ptr;
97   gint            peer_id;
98   gchar          *sender;
99 };
100
101 // TODO:
102 static void
103 g_kdbus_get_property (GObject    *object,
104                        guint       prop_id,
105                        GValue     *value,
106                        GParamSpec *pspec)
107 {
108   //GKdbus *kdbus = G_KDBUS (object);
109
110   switch (prop_id)
111     {
112       default:
113         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
114     }
115 }
116
117 // TODO:
118 static void
119 g_kdbus_set_property (GObject      *object,
120                        guint         prop_id,
121                        const GValue *value,
122                        GParamSpec   *pspec)
123 {
124   //GKdbus *kdbus = G_KDBUS (object);
125
126   switch (prop_id)
127     {
128       default:
129         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
130     }
131 }
132
133 // TODO:
134 static void
135 g_kdbus_finalize (GObject *object)
136 {
137   //GKdbus *kdbus = G_KDBUS (object);
138
139   // TODO: Posprzatac po obiekcie
140
141 }
142
143 static void
144 g_kdbus_class_init (GKdbusClass *klass)
145 {
146   GObjectClass *gobject_class G_GNUC_UNUSED = G_OBJECT_CLASS (klass);
147
148   g_type_class_add_private (klass, sizeof (GKdbusPrivate));
149
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;
153 }
154
155 static void
156 g_kdbus_initable_iface_init (GInitableIface *iface)
157 {
158   iface->init = g_kdbus_initable_init;
159 }
160
161 static void
162 g_kdbus_init (GKdbus *kdbus)
163 {
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;
170 }
171
172 static gboolean
173 g_kdbus_initable_init (GInitable *initable,
174                         GCancellable *cancellable,
175                         GError  **error)
176 {
177   GKdbus  *kdbus;
178
179   g_return_val_if_fail (G_IS_KDBUS (initable), FALSE);
180
181   kdbus = G_KDBUS (initable);
182
183   if (cancellable != NULL)
184     {
185       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
186                            _("Cancellable initialization not supported"));
187       return FALSE;
188     }
189
190   kdbus->priv->inited = TRUE;
191
192   return TRUE;
193 }
194
195 /**
196  * g_kdbus_get_fd:
197  * @kdbus: a #GKdbus.
198  *
199  * Returns: the file descriptor of the kdbus.
200  */
201 gint
202 g_kdbus_get_fd (GKdbus *kdbus)
203 {
204   g_return_val_if_fail (G_IS_KDBUS (kdbus), FALSE);
205
206   return kdbus->priv->fd;
207 }
208
209 /**
210  * g_kdbus_connect:
211  * @kdbus: a #Gkdbus.
212  */
213 gboolean
214 g_kdbus_open (GKdbus         *kdbus,
215               const gchar    *address,
216               GCancellable   *cancellable,
217               GError         **error)
218 {
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);
223   return TRUE;
224 }
225
226 /**
227  * g_kdbus_close:
228  * @kdbus: a #GKdbus
229  * @error: #GError for error reporting, or %NULL to ignore.
230  *
231  */
232 gboolean
233 g_kdbus_close (GKdbus  *kdbus,
234                 GError  **error)
235 {
236   // TODO
237
238   close(kdbus->priv->fd);
239
240   kdbus->priv->closed = TRUE;
241   kdbus->priv->fd = -1;
242   
243   return TRUE;
244 }
245
246 /**
247  * g_kdbus_is_closed:
248  * @kdbus: a #GKdbus
249  *
250  * Checks whether a kdbus is closed.
251  *
252  * Returns: %TRUE if kdbus is closed, %FALSE otherwise
253  */
254 gboolean
255 g_kdbus_is_closed (GKdbus *kdbus)
256 {
257   g_return_val_if_fail (G_IS_KDBUS (kdbus), FALSE);
258
259   return kdbus->priv->closed;
260 }
261
262 /**
263  * Registration on Kdbus bus.
264  * Hello message + unique name + mapping memory for incoming messages.
265  *
266  * @returns #TRUE on success
267  */
268 gboolean g_kdbus_register(GKdbus           *kdbus)
269 {
270         struct kdbus_cmd_hello __attribute__ ((__aligned__(8))) hello;
271
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;
282
283         if (ioctl(kdbus->priv->fd, KDBUS_CMD_HELLO, &hello))
284         {
285                 g_print("FD: %d Failed to send hello: %m, %d",kdbus->priv->fd,errno);
286                 return FALSE;
287         }
288
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;
292
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)
295         {
296                 g_print("Error when mmap: %m, %d",errno);
297                 return FALSE;
298         }
299
300         return TRUE;
301 }
302
303 /*
304  * g_kdbus_decode_msg:
305  * @kdbus_msg: kdbus message received into buffer
306  *
307  */
308 static int 
309 g_kdbus_decode_msg(GKdbus           *kdbus,
310                    struct kdbus_msg *msg, 
311                    char             *data)
312 {
313   const struct kdbus_item *item;
314   int ret_size = 0;
315
316   KDBUS_PART_FOREACH(item, msg, items)
317         {
318                 if (item->size <= KDBUS_PART_HEADER_SIZE)
319                 {
320                         g_print("  +(%llu bytes) invalid data record\n", item->size);
321                         break;  //??? continue (because dbus will find error) or break
322                 }
323
324                 switch (item->type)
325                 {
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;                     
330
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);
334                         break;
335
336       case KDBUS_MSG_REPLY_TIMEOUT:
337                                 g_print("  + KDBUS_MSG_REPLY_TIMEOUT (%llu bytes) cookie=%llu\n", item->size, msg->cookie_reply);
338
339                                 /* TODO
340         message = generate_local_error_message(msg->cookie_reply, DBUS_ERROR_NO_REPLY, NULL);
341                                 if(message == NULL)
342                                 {
343                                         ret_size = -1;
344                                         goto out;
345                                 }
346
347                                 ret_size = put_message_into_data(message, data);
348         */
349                         break;
350
351                         case KDBUS_MSG_REPLY_DEAD:
352                                 g_print("  + (%llu bytes) cookie=%llu\n", item->size, msg->cookie_reply);
353
354         /* TODO
355                                 message = generate_local_error_message(msg->cookie_reply, DBUS_ERROR_NAME_HAS_NO_OWNER, NULL);
356                                 if(message == NULL)
357                                 {
358                                         ret_size = -1;
359                                         goto out;
360                                 }
361         
362                                 ret_size = put_message_into_data(message, data);
363         */
364                         break;
365
366       /* case ... */
367     }
368   }
369
370   return ret_size;
371 }
372
373 /*
374  * g_kdbus_receive:
375  * @kdbus: a #GKdbus
376  *
377  * TODO handle errors
378  */
379 gssize
380 g_kdbus_receive (GKdbus       *kdbus,
381                  void         *data,
382                              GError       **error)
383 {
384   int ret_size;
385   guint64 __attribute__ ((__aligned__(8))) offset;
386   struct kdbus_msg *msg;
387
388   // get memory offset of msg
389   again:
390   if (ioctl(kdbus->priv->fd, KDBUS_CMD_MSG_RECV, &offset) < 0)
391   {
392           if(errno == EINTR)
393                   goto again;
394           return -1;
395   }
396
397   msg = (struct kdbus_msg *)((char*)kdbus->priv->buffer_ptr + offset);
398
399   ret_size = g_kdbus_decode_msg(kdbus, msg, (char*)data);
400
401   // Release memory occupied by msg
402   again2:
403         if (ioctl(kdbus->priv->fd, KDBUS_CMD_MSG_RELEASE, &offset) < 0)
404         {
405                 if(errno == EINTR)
406                         goto again2;
407                 return -1;
408         }
409   
410   return ret_size;
411 }
412
413 gchar* g_kdbus_get_sender(GKdbus           *kdbus)
414 {
415   return kdbus->priv->sender;
416 }
417
418 /*
419  * TODO add checks for mallocs
420  */
421 static gboolean
422 g_kdbus_send_reply(GDBusWorker     *worker, 
423                    GKdbus           *kdbus, 
424                    GDBusMessage    *dbus_msg)
425 {
426   GDBusMessage    *reply = NULL;
427   char            *unique_name = NULL;
428   char            *sender = NULL;
429
430   reply = g_dbus_message_new_method_reply(dbus_msg);
431   g_dbus_message_set_sender(reply, "org.freedesktop.DBus");
432
433   unique_name = malloc(30); // TODO should allow for Kdbus peer ID max value ?
434   sprintf(unique_name, "%i", kdbus->priv->peer_id);
435
436   sender = malloc (strlen(unique_name) + 4);
437   //if(!sender)
438                         
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);
442
443   g_dbus_message_set_body(reply, g_variant_new ("(s)", unique_name));
444   _g_dbus_worker_queue_or_deliver_received_message (worker, reply);
445 }
446
447
448
449 /**
450  * g_kdbus_send_message:
451  * @kdbus: a #GKdbus
452  */
453 gssize
454 g_kdbus_send_message (GDBusWorker     *worker,
455                       GKdbus          *kdbus,
456                       GDBusMessage    *dbus_msg,
457                       gchar           *blob,
458                       gsize           blob_size,
459                                   GError          **error)
460 {
461   struct kdbus_msg* kmsg;
462   struct kdbus_item *item;
463   guint64 kmsg_size = 0;
464   const gchar *dst;
465   guint64 dst_id = KDBUS_DST_ID_BROADCAST;
466   
467   
468   // if message to org.Freedesktop.DBus then handle differently
469   if(g_strcmp0(g_dbus_message_get_member(dbus_msg), "Hello") == 0)
470   {
471     
472
473     g_print ("kdbus_send_message: sending Hello message! \n");
474   
475     if(!g_kdbus_register(kdbus))
476     {
477       g_print ("kdbus_send_message: registering failed! \n");
478       return -1;
479     }
480
481     g_kdbus_send_reply(worker, kdbus, dbus_msg);
482     
483     g_print ("kdbus_send_message: hello sent! \n");
484     
485     goto out;
486   }
487
488   g_print ("kdbus_send_message: blob_size: %i \n", (int)blob_size);
489   
490   // get dst name
491   dst = g_dbus_message_get_destination(dbus_msg);
492   g_print ("kdbus_send_message: destination name: %s \n", dst);
493
494   kmsg_size = sizeof(struct kdbus_msg);
495   kmsg_size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); // vector for blob
496
497   if (dst)
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*/;
501
502   kmsg = malloc(kmsg_size);
503   if (!kmsg)
504   {
505         // TODO debug/error
506           return -1;
507   }
508
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);
517
518   // build message contents
519   item = kmsg->items;
520
521   MSG_ITEM_BUILD_VEC(blob, blob_size);
522
523   if (dst)
524         {
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);
529         }
530         else if (dst_id == KDBUS_DST_ID_BROADCAST)
531         {
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);
536         }
537
538 again:
539         if (ioctl(kdbus->priv->fd, KDBUS_CMD_MSG_SEND, kmsg))
540         {
541                 if(errno == EINTR)
542                         goto again;
543     else
544       g_warning ("g_kdbus_send_message: ioctl error sending kdbus message: %d (%m) \n", errno);
545   }
546   g_print ("kdbus_send_message: ioctl(CMD_MSG_SEND) sent successfully \n");
547   free(kmsg);
548
549 out:
550   return blob_size;
551 }
552
553 /***************************************************************************************************************
554
555
556 /**
557  * g_kdbus_send:
558  * @kdbus: a #GKdbus
559  */
560 /*gssize
561 g_kdbus_send (GKdbus       *kdbus,
562                const gchar   *buffer,
563                gsize          size,
564                GCancellable  *cancellable,
565                GError       **error)
566 {
567   // TODO
568 }*/
569
570
571
572
573 /**
574  * g_kdbus_receive_message:
575  * @kdbus: a #Gkdbus
576  */
577 /*gssize
578 g_kdbus_receive_message (Gkdbus                 *kdbus,
579                           GkdbusAddress         **address,
580                           GInputVector            *vectors,
581                           gint                     num_vectors,
582                           GkdbusControlMessage ***messages,
583                           gint                    *num_messages,
584                           gint                    *flags,
585                           GCancellable            *cancellable,
586                           GError                 **error)
587 {
588   //TODO
589 }*/