2747be532bb8ee9e1ecfb6e29e45f3685fd42144
[platform/upstream/dbus.git] / dbus / dbus-transport-kdbus.c
1 /*
2  * dbus-transport-kdbus.c
3  *
4  * Transport layer using kdbus
5  *
6  *  Created on: Jun 20, 2013
7  *      Author: r.pajak
8  *
9  *
10  */
11
12 #include "dbus-transport.h"
13 #include "dbus-transport-kdbus.h"
14 #include <dbus/dbus-transport-protected.h>
15 #include "dbus-connection-internal.h"
16 #include "kdbus.h"
17 #include "dbus-watch.h"
18 #include "dbus-errors.h"
19 #include "dbus-bus.h"
20 #include <fcntl.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <sys/ioctl.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <sys/mman.h>
29 #include <linux/types.h>
30
31 #define KDBUS_ALIGN8(l) (((l) + 7) & ~7)
32 #define KDBUS_PART_HEADER_SIZE offsetof(struct kdbus_item, data)
33 #define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8((s) + KDBUS_PART_HEADER_SIZE)
34
35 #define KDBUS_PART_NEXT(part) \
36         (typeof(part))(((uint8_t *)part) + KDBUS_ALIGN8((part)->size))
37 #define KDBUS_PART_FOREACH(part, head, first)                           \
38         for (part = (head)->first;                                      \
39              (uint8_t *)(part) < (uint8_t *)(head) + (head)->size;      \
40              part = KDBUS_PART_NEXT(part))
41 #define POOL_SIZE (16 * 1024LU * 1024LU)
42
43 /*struct and type below copied from dbus_transport_socket.c
44  * needed for _dbus_transport_new_for_socket_kdbus and kdbus_vtable(?)
45  * todo maybe DBusTransportSocket and _dbus_transport_new_for_socket_kdbus not needed here -
46  * maybe only static const DBusTransportVTable implementation will be enough
47  */
48
49 /**
50  * Opaque object representing a socket file descriptor transport.
51  */
52 typedef struct DBusTransportSocket DBusTransportSocket;
53
54 /**
55  * Implementation details of DBusTransportSocket. All members are private.
56  */
57 struct DBusTransportSocket
58 {
59   DBusTransport base;                   /**< Parent instance */
60   int fd;                               /**< File descriptor. */
61   DBusWatch *read_watch;                /**< Watch for readability. */
62   DBusWatch *write_watch;               /**< Watch for writability. */
63
64   int max_bytes_read_per_iteration;     /**< To avoid blocking too long. */
65   int max_bytes_written_per_iteration;  /**< To avoid blocking too long. */
66
67   int message_bytes_written;            /**< Number of bytes of current
68                                          *   outgoing message that have
69                                          *   been written.
70                                          */
71   DBusString encoded_outgoing;          /**< Encoded version of current
72                                          *   outgoing message.
73                                          */
74   DBusString encoded_incoming;          /**< Encoded version of current
75                                          *   incoming data.
76                                          */
77   void* kdbus_mmap_ptr;
78 };
79
80
81 static dbus_bool_t
82 socket_get_socket_fd (DBusTransport *transport,
83                       int           *fd_p)
84 {
85   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
86
87   *fd_p = socket_transport->fd;
88
89   return TRUE;
90 }
91
92 static int kdbus_write_msg(DBusConnection *connection, DBusMessage *message, int fd)
93 {
94         struct kdbus_msg *msg;
95         struct kdbus_item *item;
96         uint64_t size;
97         const char *name;
98         uint64_t dst_id = KDBUS_DST_ID_BROADCAST;
99     const DBusString *header;
100     const DBusString *body;
101     uint64_t ret_size;
102
103 //    uint64_t i;
104
105     if((name = dbus_message_get_destination(message)))
106     {
107         _dbus_verbose ("do writing destination: %s\n", name); //todo can be removed at the end
108         dst_id = KDBUS_DST_ID_WELL_KNOWN_NAME;
109         if((name[0] == ':') && (name[1] == '1') && (name[2] == '.')) //if name starts with :1. it is a unique name and should be send as number
110         {
111                 dst_id = strtoll(&name[3], NULL, 10);
112                 _dbus_verbose ("do writing uniqe id: %lu\n", dst_id); //todo can be removed at the end
113                 name = NULL;
114         }
115     }
116
117     _dbus_message_get_network_data (message, &header, &body);
118     ret_size = (uint64_t)_dbus_string_get_length(header);
119
120   /*  fprintf (stderr, "\nheader:\n");
121     for(i=0; i < ret_size; i++)
122     {
123         fprintf (stderr, "%02x", _dbus_string_get_byte(header,i));
124     }
125     fprintf (stderr, "\nret size: %lu, i: %lu\n", ret_size, i);*/
126
127 //    _dbus_verbose("padding bytes for header: %lu \n", KDBUS_ALIGN8(ret_size) - ret_size);
128
129     size = sizeof(struct kdbus_msg);
130         size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
131         size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
132
133         if (dst_id == KDBUS_DST_ID_BROADCAST)
134                 size += KDBUS_PART_HEADER_SIZE + 64;
135
136         if (name)
137                 size += KDBUS_ITEM_SIZE(strlen(name) + 1);
138
139         msg = malloc(size);
140         if (!msg)
141         {
142                 _dbus_verbose("Error allocating memory for: %s,%s\n", _dbus_strerror (errno), _dbus_error_from_errno (errno));
143                 return -1;
144         }
145
146         memset(msg, 0, size);
147         msg->size = size;
148         msg->src_id = strtoll(dbus_bus_get_unique_name(connection), NULL , 10);
149         _dbus_verbose("sending msg, src_id=%llu\n", msg->src_id);
150         msg->dst_id = name ? 0 : dst_id;
151         msg->cookie = dbus_message_get_serial(message);
152         msg->payload_type = KDBUS_PAYLOAD_DBUS1;
153
154         item = msg->items;
155
156         if (name)
157         {
158                 item->type = KDBUS_MSG_DST_NAME;
159                 item->size = KDBUS_PART_HEADER_SIZE + strlen(name) + 1;
160                 strcpy(item->str, name);
161                 item = KDBUS_PART_NEXT(item);
162         }
163
164         item->type = KDBUS_MSG_PAYLOAD_VEC;
165         item->size = KDBUS_PART_HEADER_SIZE + sizeof(struct kdbus_vec);
166         item->vec.address = (uint64_t)_dbus_string_get_const_data(header);
167         item->vec.size = ret_size;
168         item = KDBUS_PART_NEXT(item);
169
170         item->type = KDBUS_MSG_PAYLOAD_VEC;
171         item->size = KDBUS_PART_HEADER_SIZE + sizeof(struct kdbus_vec);
172         item->vec.address = (uint64_t)_dbus_string_get_const_data(body);
173         item->vec.size = (uint64_t)_dbus_string_get_length(body);
174         ret_size += item->vec.size;
175
176   /*  fprintf (stderr, "\nbody:\n");
177     for(i=0; i < item->vec.size; i++)
178     {
179         fprintf (stderr, "%02x", _dbus_string_get_byte(body,i));
180     }
181     fprintf (stderr, "\nitem->vec.size: %llu, i: %lu\n", item->vec.size, i);*/
182
183         item = KDBUS_PART_NEXT(item);
184
185         if (dst_id == KDBUS_DST_ID_BROADCAST)
186         {
187                 item->type = KDBUS_MSG_BLOOM;
188                 item->size = KDBUS_PART_HEADER_SIZE + 64;
189         }
190
191         again:
192         if (ioctl(fd, KDBUS_CMD_MSG_SEND, msg))
193         {
194                 if(errno == EINTR)
195                         goto again;
196                 _dbus_verbose("kdbus error sending message: err %d (%m)\n", errno);
197                 return -1;
198         }
199
200         free(msg);
201
202         return ret_size;
203 }
204
205 static int kdbus_write_msg_encoded(DBusMessage *message, DBusTransportSocket *socket_transport)
206 {
207         struct kdbus_msg *msg;
208         struct kdbus_item *item;
209         uint64_t size;
210         const char *name;
211         uint64_t dst_id = KDBUS_DST_ID_BROADCAST;
212     uint64_t ret_size;
213
214     if((name = dbus_message_get_destination(message)))
215     {
216         _dbus_verbose ("do writing encoded message destination: %s\n", name); //todo can be removed at the end
217         if((name[0] == '1') && (name[1] == ':'))
218         {
219                 dst_id = strtoll(&name[2], NULL, 10);
220                 _dbus_verbose ("do writing encoded message uniqe id form name: %lu\n", dst_id); //todo can be removed at the end
221                 name = NULL;
222         }
223     }
224
225     size = sizeof(struct kdbus_msg);
226         size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
227
228         if (dst_id == KDBUS_DST_ID_BROADCAST)
229                 size += KDBUS_PART_HEADER_SIZE + 64;
230
231         if (name)
232                 size += KDBUS_ITEM_SIZE(strlen(name) + 1);
233
234         msg = malloc(size);
235         if (!msg)
236         {
237                 _dbus_verbose("Error allocating memory for: %s,%s\n", _dbus_strerror (errno), _dbus_error_from_errno (errno));
238                 return -1;
239         }
240
241         memset(msg, 0, size);
242         msg->size = size;
243         msg->src_id = strtoll(dbus_bus_get_unique_name(socket_transport->base.connection), NULL , 10);
244         _dbus_verbose("sending encoded msg, src_id=%llu\n", msg->src_id);
245         msg->dst_id = name ? 0 : dst_id;
246         msg->cookie = dbus_message_get_serial(message);
247         msg->payload_type = KDBUS_PAYLOAD_DBUS1;
248
249         item = msg->items;
250
251         if (name)
252         {
253                 item->type = KDBUS_MSG_DST_NAME;
254                 item->size = KDBUS_PART_HEADER_SIZE + strlen(name) + 1;
255                 strcpy(item->str, name);
256                 item = KDBUS_PART_NEXT(item);
257         }
258
259         item->type = KDBUS_MSG_PAYLOAD_VEC;
260         item->size = KDBUS_PART_HEADER_SIZE + sizeof(struct kdbus_vec);
261         item->vec.address = (uint64_t)&socket_transport->encoded_outgoing;
262         item->vec.size = _dbus_string_get_length (&socket_transport->encoded_outgoing);
263         item = KDBUS_PART_NEXT(item);
264
265         if (dst_id == KDBUS_DST_ID_BROADCAST)
266         {
267                 item->type = KDBUS_MSG_BLOOM;
268                 item->size = KDBUS_PART_HEADER_SIZE + 64;
269         }
270
271         again:
272         if (ioctl(socket_transport->fd, KDBUS_CMD_MSG_SEND, msg))
273         {
274                 if(errno == EINTR)
275                         goto again;
276                 _dbus_verbose("error sending encoded message: err %d (%m)\n", errno);
277                 return -1;
278         }
279
280         free(msg);
281
282         return ret_size;
283 }
284
285 //todo functions from kdbus-utli.c for printing messages - maybe to remove at the end
286 char *msg_id(uint64_t id, char *buf);
287 char *msg_id(uint64_t id, char *buf)
288 {
289         if (id == 0)
290                 return "KERNEL";
291         if (id == ~0ULL)
292                 return "BROADCAST";
293         sprintf(buf, "%llu", (unsigned long long)id);
294         return buf;
295 }
296
297 struct kdbus_enum_table {
298         long long id;
299         const char *name;
300 };
301 #define _STRINGIFY(x) #x
302 #define STRINGIFY(x) _STRINGIFY(x)
303 #define ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0]))
304 #define TABLE(what) static struct kdbus_enum_table kdbus_table_##what[]
305 #define ENUM(_id) { .id=_id, .name=STRINGIFY(_id) }
306 #define LOOKUP(what)                                                            \
307         const char *enum_##what(long long id) {                                 \
308         size_t i; \
309                 for (i = 0; i < ELEMENTSOF(kdbus_table_##what); i++)    \
310                         if (id == kdbus_table_##what[i].id)                     \
311                                 return kdbus_table_##what[i].name;              \
312                 return "UNKNOWN";                                               \
313         }
314 const char *enum_MSG(long long id);
315 TABLE(MSG) = {
316         ENUM(_KDBUS_MSG_NULL),
317         ENUM(KDBUS_MSG_PAYLOAD_VEC),
318         ENUM(KDBUS_MSG_PAYLOAD_OFF),
319         ENUM(KDBUS_MSG_PAYLOAD_MEMFD),
320         ENUM(KDBUS_MSG_FDS),
321         ENUM(KDBUS_MSG_BLOOM),
322         ENUM(KDBUS_MSG_DST_NAME),
323         ENUM(KDBUS_MSG_SRC_CREDS),
324         ENUM(KDBUS_MSG_SRC_PID_COMM),
325         ENUM(KDBUS_MSG_SRC_TID_COMM),
326         ENUM(KDBUS_MSG_SRC_EXE),
327         ENUM(KDBUS_MSG_SRC_CMDLINE),
328         ENUM(KDBUS_MSG_SRC_CGROUP),
329         ENUM(KDBUS_MSG_SRC_CAPS),
330         ENUM(KDBUS_MSG_SRC_SECLABEL),
331         ENUM(KDBUS_MSG_SRC_AUDIT),
332         ENUM(KDBUS_MSG_SRC_NAMES),
333         ENUM(KDBUS_MSG_TIMESTAMP),
334         ENUM(KDBUS_MSG_NAME_ADD),
335         ENUM(KDBUS_MSG_NAME_REMOVE),
336         ENUM(KDBUS_MSG_NAME_CHANGE),
337         ENUM(KDBUS_MSG_ID_ADD),
338         ENUM(KDBUS_MSG_ID_REMOVE),
339         ENUM(KDBUS_MSG_REPLY_TIMEOUT),
340         ENUM(KDBUS_MSG_REPLY_DEAD),
341 };
342 LOOKUP(MSG);
343 const char *enum_PAYLOAD(long long id);
344 TABLE(PAYLOAD) = {
345         ENUM(KDBUS_PAYLOAD_KERNEL),
346         ENUM(KDBUS_PAYLOAD_DBUS1),
347         ENUM(KDBUS_PAYLOAD_GVARIANT),
348 };
349 LOOKUP(PAYLOAD);
350
351   //todo handling of all msg items
352 static int kdbus_decode_msg(const struct kdbus_msg* msg, char *data, void* mmap_ptr)
353 {
354         const struct kdbus_item *item = msg->items;
355         char buf[32];  //todo to be removed after development
356         int ret_size = 0;
357         DBusMessage *message = NULL;
358         DBusMessageIter args;
359         char* pStringMallocked = NULL;
360         const char* dbus = "org.freedesktop.DBus";
361         const char* emptyString = "";
362     const DBusString *header;
363     const DBusString *body;
364     int size;
365     const char* pString = NULL;
366
367 //    uint64_t i;
368
369         _dbus_verbose("MESSAGE: %s (%llu bytes) flags=0x%llx, %s â†’ %s, cookie=%llu, timeout=%llu\n",
370                 enum_PAYLOAD(msg->payload_type), (unsigned long long) msg->size,
371                 (unsigned long long) msg->flags,
372                 msg_id(msg->src_id, buf), msg_id(msg->dst_id, buf),
373                 (unsigned long long) msg->cookie, (unsigned long long) msg->timeout_ns);
374
375         KDBUS_PART_FOREACH(item, msg, items)
376         {
377                 if (item->size <= KDBUS_PART_HEADER_SIZE)
378                 {
379                         _dbus_verbose("  +%s (%llu bytes) invalid data record\n", enum_MSG(item->type), item->size);
380                         break;  //todo to be discovered and rewritten
381                 }
382
383                 switch (item->type)
384                 {
385                         case KDBUS_MSG_PAYLOAD_OFF:
386                         {
387                                 char *s;
388
389                                 if (item->vec.offset == ~0ULL)
390                                         s = "[padding bytes]";
391                                 else
392                                 {
393 //                                      uint64_t i;
394
395                                         s = (char *)mmap_ptr + item->vec.offset;
396                                 /*      fprintf(stderr,"\nmmap: %lu", (uint64_t)mmap_ptr);
397                                         fprintf (stderr, "\nheader: %llu\n", item->vec.size);
398                                     for(i=0; i < item->vec.size; i++)
399                                     {
400                                         fprintf (stderr, "%02x", (int)s[i]);
401                                     }
402                                     fprintf (stderr, "\nret size: %llu, i: %lu\n", item->vec.size, i);*/
403
404                                         memcpy(data, s, item->vec.size);
405                                         data += item->vec.size;
406                                         ret_size += item->vec.size;
407                                 }
408
409                                 _dbus_verbose("  +%s (%llu bytes) off=%llu size=%llu '%s'\n",
410                                            enum_MSG(item->type), item->size,
411                                            (unsigned long long)item->vec.offset,
412                                            (unsigned long long)item->vec.size, s);
413                                 break;
414                         }
415
416                         case KDBUS_MSG_PAYLOAD_MEMFD:
417                         {
418                                 char *buf;
419                                 uint64_t size;
420
421                                 buf = mmap(NULL, item->memfd.size, PROT_READ, MAP_SHARED, item->memfd.fd, 0);
422                                 if (buf == MAP_FAILED) {
423                                         _dbus_verbose("mmap() fd=%i failed:%m", item->memfd.fd);
424                                         break;
425                                 }
426
427                                 if (ioctl(item->memfd.fd, KDBUS_CMD_MEMFD_SIZE_GET, &size) < 0) {
428                                         _dbus_verbose("KDBUS_CMD_MEMFD_SIZE_GET failed: %m\n");
429                                         break;
430                                 }
431
432                                 _dbus_verbose("  +%s (%llu bytes) fd=%i size=%llu filesize=%llu '%s'\n",
433                                            enum_MSG(item->type), item->size, item->memfd.fd,
434                                            (unsigned long long)item->memfd.size, (unsigned long long)size, buf);
435                                 break;
436                         }
437
438                         case KDBUS_MSG_SRC_CREDS:
439                                 _dbus_verbose("  +%s (%llu bytes) uid=%lld, gid=%lld, pid=%lld, tid=%lld, starttime=%lld\n",
440                                         enum_MSG(item->type), item->size,
441                                         item->creds.uid, item->creds.gid,
442                                         item->creds.pid, item->creds.tid,
443                                         item->creds.starttime);
444                         break;
445
446                         case KDBUS_MSG_SRC_PID_COMM:
447                         case KDBUS_MSG_SRC_TID_COMM:
448                         case KDBUS_MSG_SRC_EXE:
449                         case KDBUS_MSG_SRC_CGROUP:
450                         case KDBUS_MSG_SRC_SECLABEL:
451                         case KDBUS_MSG_DST_NAME:
452                                 _dbus_verbose("  +%s (%llu bytes) '%s' (%zu)\n",
453                                            enum_MSG(item->type), item->size, item->str, strlen(item->str));
454                                 break;
455
456                         case KDBUS_MSG_SRC_CMDLINE:
457                         case KDBUS_MSG_SRC_NAMES: {
458                                 size_t size = item->size - KDBUS_PART_HEADER_SIZE;
459                                 const char *str = item->str;
460                                 int count = 0;
461
462                                 _dbus_verbose("  +%s (%llu bytes) ", enum_MSG(item->type), item->size);
463                                 while (size) {
464                                         _dbus_verbose("'%s' ", str);
465                                         size -= strlen(str) + 1;
466                                         str += strlen(str) + 1;
467                                         count++;
468                                 }
469
470                                 _dbus_verbose("(%d string%s)\n", count, (count == 1) ? "" : "s");
471                                 break;
472                         }
473
474                         case KDBUS_MSG_SRC_AUDIT:
475                                 _dbus_verbose("  +%s (%llu bytes) loginuid=%llu sessionid=%llu\n",
476                                            enum_MSG(item->type), item->size,
477                                            (unsigned long long)item->data64[0],
478                                            (unsigned long long)item->data64[1]);
479                                 break;
480
481                         case KDBUS_MSG_SRC_CAPS: {
482                                 int n;
483                                 const uint32_t *cap;
484                                 int i;
485
486                                 _dbus_verbose("  +%s (%llu bytes) len=%llu bytes)\n",
487                                            enum_MSG(item->type), item->size,
488                                            (unsigned long long)item->size - KDBUS_PART_HEADER_SIZE);
489
490                                 cap = item->data32;
491                                 n = (item->size - KDBUS_PART_HEADER_SIZE) / 4 / sizeof(uint32_t);
492
493                                 _dbus_verbose("    CapInh=");
494                                 for (i = 0; i < n; i++)
495                                         _dbus_verbose("%08x", cap[(0 * n) + (n - i - 1)]);
496
497                                 _dbus_verbose(" CapPrm=");
498                                 for (i = 0; i < n; i++)
499                                         _dbus_verbose("%08x", cap[(1 * n) + (n - i - 1)]);
500
501                                 _dbus_verbose(" CapEff=");
502                                 for (i = 0; i < n; i++)
503                                         _dbus_verbose("%08x", cap[(2 * n) + (n - i - 1)]);
504
505                                 _dbus_verbose(" CapInh=");
506                                 for (i = 0; i < n; i++)
507                                         _dbus_verbose("%08x", cap[(3 * n) + (n - i - 1)]);
508                                 _dbus_verbose("\n");
509                                 break;
510                         }
511
512                         case KDBUS_MSG_TIMESTAMP:
513                                 _dbus_verbose("  +%s (%llu bytes) realtime=%lluns monotonic=%lluns\n",
514                                            enum_MSG(item->type), item->size,
515                                            (unsigned long long)item->timestamp.realtime_ns,
516                                            (unsigned long long)item->timestamp.monotonic_ns);
517                                 break;
518
519                         case KDBUS_MSG_REPLY_TIMEOUT:  //todo translate to kdbus message
520                                 _dbus_verbose("  +%s (%llu bytes) cookie=%llu\n",
521                                            enum_MSG(item->type), item->size, msg->cookie_reply);
522                                 break;
523
524                         case KDBUS_MSG_NAME_ADD:
525                                 _dbus_verbose("  +%s (%llu bytes) '%s', old id=%lld, new id=%lld, flags=0x%llx\n",
526                                         enum_MSG(item->type), (unsigned long long) item->size,
527                                         item->name_change.name, item->name_change.old_id,
528                                         item->name_change.new_id, item->name_change.flags);
529
530                                 pStringMallocked = malloc (sizeof(item->name_change.new_id)*2.5 + 4);
531                                 if(pStringMallocked)
532                                 {
533                                         strcpy(pStringMallocked,":1.");
534                                         sprintf(&pStringMallocked[3],"%llu",item->name_change.new_id);
535                                         _dbus_verbose ("Name added for id: %s\n", pStringMallocked);  //todo to be removed
536                                 }
537                                 else
538                                         return -1;
539
540                                 message = dbus_message_new_signal("/org/freedesktop/DBus", // object name of the signal
541                                             dbus, // interface name of the signal
542                                             "NameOwnerChanged"); // name of the signal
543                                 if(message == NULL)
544                                 {
545                                         ret_size = -1;
546                                         goto out;
547                                 }
548
549                                 pString = item->name_change.name;
550                                 _dbus_verbose ("Name added: %s\n", pString);
551                             dbus_message_iter_init_append(message, &args);
552                             if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING,&pString))
553                                 {
554                                         ret_size = -1;
555                                 goto out;
556                                 }
557                             if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &emptyString))
558                                 {
559                                         ret_size = -1;
560                                 goto out;
561                                 }
562                             if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &pStringMallocked))
563                                 {
564                                         ret_size = -1;
565                                 goto out;
566                                 }
567
568                                 dbus_message_set_sender(message, dbus);
569                                 dbus_message_set_serial(message, 1);
570
571                             dbus_message_lock (message);
572                             _dbus_message_get_network_data (message, &header, &body);
573                             size = _dbus_string_get_length(header);
574                                 memcpy(data, _dbus_string_get_const_data(header), size);
575                                 data += size;
576                                 ret_size += size;
577                                 size = _dbus_string_get_length(body);
578                                 memcpy(data, _dbus_string_get_const_data(body), size);
579                                 data += size;
580                                 ret_size += size;
581                         break;
582
583                         case KDBUS_MSG_NAME_REMOVE:
584                                 _dbus_verbose("  +%s (%llu bytes) '%s', old id=%lld, new id=%lld, flags=0x%llx\n",
585                                         enum_MSG(item->type), (unsigned long long) item->size,
586                                         item->name_change.name, item->name_change.old_id,
587                                         item->name_change.new_id, item->name_change.flags);
588
589                                 pStringMallocked = malloc (sizeof(item->name_change.old_id)*2.5 + 4);
590                                 if(pStringMallocked)
591                                 {
592                                         strcpy(pStringMallocked,":1.");
593                                         sprintf(&pStringMallocked[3],"%llu",item->name_change.old_id);
594                                         _dbus_verbose ("Name removed for id: %s\n", pStringMallocked);  //todo to be removed
595                                 }
596                                 else
597                                         return -1;
598
599                                 message = dbus_message_new_signal("/org/freedesktop/DBus", // object name of the signal
600                                             dbus, // interface name of the signal
601                                             "NameOwnerChanged"); // name of the signal
602                                 if(message == NULL)
603                                 {
604                                         ret_size = -1;
605                                         goto out;
606                                 }
607
608                                 pString = item->name_change.name;
609                                 _dbus_verbose ("Name removed: %s\n", pString);
610                             dbus_message_iter_init_append(message, &args);
611                             if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING,&pString))
612                                 {
613                                         ret_size = -1;
614                                 goto out;
615                                 }
616                             if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &pStringMallocked))
617                                 {
618                                         ret_size = -1;
619                                 goto out;
620                                 }
621                             if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &emptyString))
622                                 {
623                                         ret_size = -1;
624                                 goto out;
625                                 }
626
627                                 dbus_message_set_sender(message, dbus);
628                                 dbus_message_set_serial(message, 1);
629
630                             dbus_message_lock (message);
631                             _dbus_message_get_network_data (message, &header, &body);
632                             size = _dbus_string_get_length(header);
633                                 memcpy(data, _dbus_string_get_const_data(header), size);
634                                 data += size;
635                                 ret_size += size;
636                                 size = _dbus_string_get_length(body);
637                                 memcpy(data, _dbus_string_get_const_data(body), size);
638                                 data += size;
639                                 ret_size += size;
640
641                         /*              fprintf (stderr, "\nheader: %llu\n", _dbus_string_get_length(header));
642                                     for(i=0; i < _dbus_string_get_length(header); i++)
643                                     {
644                                         fprintf (stderr, "%02x", (int)_dbus_string_get_byte(header,i));
645                                     }
646                                         fprintf (stderr, "\nbody: %llu\n", _dbus_string_get_length(body));
647                                     for(i=0; i < _dbus_string_get_length(body); i++)
648                                     {
649                                         fprintf (stderr, "%02x", (int)_dbus_string_get_byte(body,i));
650                                     }
651                                         fprintf (stderr, "\ndata: %llu\n", retsize);
652                                     for(i=0; i < _dbus_string_get_length(body); i++)
653                                     {
654                                         fprintf (stderr, "%02x", (int)_dbus_string_get_byte(body,i));
655                                     }*/
656
657                         break;
658
659                         case KDBUS_MSG_NAME_CHANGE:
660                                 _dbus_verbose("  +%s (%llu bytes) '%s', old id=%lld, new id=%lld, flags=0x%llx\n",
661                                         enum_MSG(item->type), (unsigned long long) item->size,
662                                         item->name_change.name, item->name_change.old_id,
663                                         item->name_change.new_id, item->name_change.flags);
664
665                                 pStringMallocked = malloc (sizeof(item->name_change.new_id)*2.5 + 4);
666                                 if(pStringMallocked)
667                                 {
668                                         strcpy(pStringMallocked,":1.");
669                                         sprintf(&pStringMallocked[3],"%llu",item->name_change.old_id);
670                                         _dbus_verbose ("Old id: %s\n", pStringMallocked);  //todo to be removed
671                                 }
672                                 else
673                                         return -1;
674
675                                 message = dbus_message_new_signal("/org/freedesktop/DBus", // object name of the signal
676                                             dbus, // interface name of the signal
677                                             "NameOwnerChanged"); // name of the signal
678                                 if(message == NULL)
679                                 {
680                                         ret_size = -1;
681                                         goto out;
682                                 }
683
684                                 pString = item->name_change.name;
685                                 _dbus_verbose ("Name changed: %s\n", pString);
686                             dbus_message_iter_init_append(message, &args);
687                             if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING,&pString))
688                                 {
689                                         ret_size = -1;
690                                 goto out;
691                                 }
692                             if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &pStringMallocked))
693                                 {
694                                         ret_size = -1;
695                                 goto out;
696                                 }
697                             sprintf(&pStringMallocked[3],"%llu",item->name_change.new_id);
698                             _dbus_verbose ("New id: %s\n", pStringMallocked);  //todo to be removed
699                             if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &pStringMallocked))
700                                 {
701                                         ret_size = -1;
702                                 goto out;
703                                 }
704
705                                 dbus_message_set_sender(message, dbus);
706                                 dbus_message_set_serial(message, 1);
707
708                             dbus_message_lock (message);
709                             _dbus_message_get_network_data (message, &header, &body);
710                             size = _dbus_string_get_length(header);
711                                 memcpy(data, _dbus_string_get_const_data(header), size);
712                                 data += size;
713                                 ret_size += size;
714                                 size = _dbus_string_get_length(body);
715                                 memcpy(data, _dbus_string_get_const_data(body), size);
716                                 data += size;
717                                 ret_size += size;
718                         break;
719
720                         case KDBUS_MSG_ID_ADD:
721                                 _dbus_verbose("  +%s (%llu bytes) id=%llu flags=%llu\n",
722                                            enum_MSG(item->type), (unsigned long long) item->size,
723                                            (unsigned long long) item->id_change.id,
724                                            (unsigned long long) item->id_change.flags);
725
726                                 pStringMallocked = malloc (sizeof(item->id_change.id)*2.5 + 4);
727                                 if(pStringMallocked)
728                                 {
729                                         strcpy(pStringMallocked,":1.");
730                                         sprintf(&pStringMallocked[3],"%llu",item->id_change.id);
731                                         _dbus_verbose ("Id added: %s\n", pStringMallocked);  //todo to be removed
732                                 }
733                                 else
734                                         return -1;
735
736                                 message = dbus_message_new_signal("/org/freedesktop/DBus", // object name of the signal
737                                             dbus, // interface name of the signal
738                                             "NameOwnerChanged"); // name of the signal
739                                 if(message == NULL)
740                                 {
741                                         ret_size = -1;
742                                         goto out;
743                                 }
744
745                             dbus_message_iter_init_append(message, &args);
746                             if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &pStringMallocked))
747                                 {
748                                         ret_size = -1;
749                                 goto out;
750                                 }
751                             if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &emptyString))
752                                 {
753                                         ret_size = -1;
754                                 goto out;
755                                 }
756                             if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &pStringMallocked))
757                                 {
758                                         ret_size = -1;
759                                 goto out;
760                                 }
761
762                                 dbus_message_set_sender(message, dbus);
763                                 dbus_message_set_serial(message, 1);
764
765                             dbus_message_lock (message);
766                             _dbus_message_get_network_data (message, &header, &body);
767                             size = _dbus_string_get_length(header);
768                                 memcpy(data, _dbus_string_get_const_data(header), size);
769                                 data += size;
770                                 ret_size += size;
771                                 size = _dbus_string_get_length(body);
772                                 memcpy(data, _dbus_string_get_const_data(body), size);
773                                 data += size;
774                                 ret_size += size;
775                         break;
776
777                         case KDBUS_MSG_ID_REMOVE:
778                                 _dbus_verbose("  +%s (%llu bytes) id=%llu flags=%llu\n",
779                                            enum_MSG(item->type), (unsigned long long) item->size,
780                                            (unsigned long long) item->id_change.id,
781                                            (unsigned long long) item->id_change.flags);
782
783                                 pStringMallocked = malloc (sizeof(item->id_change.id)*2.5 + 4);
784                                 if(pStringMallocked)
785                                 {
786                                         strcpy(pStringMallocked,":1.");
787                                         sprintf(&pStringMallocked[3],"%llu",item->id_change.id);
788                                         _dbus_verbose ("Id removed: %s\n", pStringMallocked);  //todo to be removed
789                                 }
790                                 else
791                                         return -1;
792
793                                 message = dbus_message_new_signal("/org/freedesktop/DBus", // object name of the signal
794                                             dbus, // interface name of the signal
795                                             "NameOwnerChanged"); // name of the signal
796                                 if(message == NULL)
797                                 {
798                                         ret_size = -1;
799                                         goto out;
800                                 }
801
802                             dbus_message_iter_init_append(message, &args);
803                             if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &pStringMallocked))
804                                 {
805                                         ret_size = -1;
806                                 goto out;
807                                 }
808                             if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &pStringMallocked))
809                                 {
810                                         ret_size = -1;
811                                 goto out;
812                                 }
813                             if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &emptyString))
814                                 {
815                                         ret_size = -1;
816                                 goto out;
817                                 }
818
819                                 dbus_message_set_sender(message, dbus);
820                                 dbus_message_set_serial(message, 1);
821
822                             dbus_message_lock (message);
823                             _dbus_message_get_network_data (message, &header, &body);
824                             size = _dbus_string_get_length(header);
825                                 memcpy(data, _dbus_string_get_const_data(header), size);
826                                 data += size;
827                                 ret_size += size;
828                                 size = _dbus_string_get_length(body);
829                                 memcpy(data, _dbus_string_get_const_data(body), size);
830                                 data += size;
831                                 ret_size += size;
832                         break;
833
834                         default:
835                                 _dbus_verbose("  +%s (%llu bytes)\n", enum_MSG(item->type), item->size);
836                                 break;
837                 }
838         }
839
840         if ((char *)item - ((char *)msg + msg->size) >= 8)
841                 _dbus_verbose("invalid padding at end of message\n");
842
843 out:
844         if(message)
845                 dbus_message_unref(message);
846         if(pStringMallocked)
847                 free((void*)pStringMallocked);
848         return ret_size;
849 }
850
851 static int kdbus_read_message(DBusTransportSocket *socket_transport, DBusString *buffer)
852 {
853         int ret_size;
854         uint64_t offset;
855         struct kdbus_msg *msg;
856         int ret;
857         int start;
858         char *data;
859
860 //      int i;
861
862         _dbus_assert (socket_transport->max_bytes_read_per_iteration >= 0);
863         start = _dbus_string_get_length (buffer);
864         if (!_dbus_string_lengthen (buffer, socket_transport->max_bytes_read_per_iteration))
865         {
866                 errno = ENOMEM;
867             return -1;
868         }
869         data = _dbus_string_get_data_len (buffer, start, socket_transport->max_bytes_read_per_iteration);
870
871         again:
872         ret = ioctl(socket_transport->fd, KDBUS_CMD_MSG_RECV, &offset);
873         if (ret < 0)
874         {
875                 if(errno == EINTR)
876                         goto again;
877                 _dbus_verbose("kdbus error receiving message: %d (%m)\n", ret);
878                 _dbus_string_set_length (buffer, start);
879                 return -1;
880         }
881
882         msg = (struct kdbus_msg *)((char*)socket_transport->kdbus_mmap_ptr + offset);
883
884         ret_size = kdbus_decode_msg(msg, data, socket_transport->kdbus_mmap_ptr);
885 /*      fprintf (stderr, "\nmessage! start: %u, ret_size: %u\n", start, ret_size);
886     for(i=0; i < ret_size; i++)
887     {
888         fprintf (stderr, "%02x", (int)data[i]);
889     }
890     fprintf (stderr, "\nret size: %u, i: %u\n", ret_size, i);*/
891         _dbus_string_set_length (buffer, start + ret_size);
892
893         again2:
894         ret = ioctl(socket_transport->fd, KDBUS_CMD_MSG_RELEASE, &offset);
895         if (ret < 0)
896         {
897                 if(errno == EINTR)
898                         goto again2;
899                 _dbus_verbose("kdbus error freeing message: %d (%m)\n", ret);
900                 return -1;
901         }
902
903         return ret_size;
904 }
905
906 static void
907 free_watches (DBusTransport *transport)
908 {
909   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
910
911   _dbus_verbose ("start\n");
912
913   if (socket_transport->read_watch)
914     {
915       if (transport->connection)
916         _dbus_connection_remove_watch_unlocked (transport->connection,
917                                                 socket_transport->read_watch);
918       _dbus_watch_invalidate (socket_transport->read_watch);
919       _dbus_watch_unref (socket_transport->read_watch);
920       socket_transport->read_watch = NULL;
921     }
922
923   if (socket_transport->write_watch)
924     {
925       if (transport->connection)
926         _dbus_connection_remove_watch_unlocked (transport->connection,
927                                                 socket_transport->write_watch);
928       _dbus_watch_invalidate (socket_transport->write_watch);
929       _dbus_watch_unref (socket_transport->write_watch);
930       socket_transport->write_watch = NULL;
931     }
932
933   _dbus_verbose ("end\n");
934 }
935
936 static void
937 socket_finalize (DBusTransport *transport)
938 {
939   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
940
941   _dbus_verbose ("\n");
942
943   free_watches (transport);
944
945   _dbus_string_free (&socket_transport->encoded_outgoing);
946   _dbus_string_free (&socket_transport->encoded_incoming);
947
948   _dbus_transport_finalize_base (transport);
949
950   _dbus_assert (socket_transport->read_watch == NULL);
951   _dbus_assert (socket_transport->write_watch == NULL);
952
953   dbus_free (transport);
954 }
955
956 static void
957 check_write_watch (DBusTransport *transport)
958 {
959   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
960   dbus_bool_t needed;
961
962   if (transport->connection == NULL)
963     return;
964
965   if (transport->disconnected)
966     {
967       _dbus_assert (socket_transport->write_watch == NULL);
968       return;
969     }
970
971   _dbus_transport_ref (transport);
972
973   if (_dbus_transport_get_is_authenticated (transport))
974     needed = _dbus_connection_has_messages_to_send_unlocked (transport->connection);
975   else
976     {
977       if (transport->send_credentials_pending)
978         needed = TRUE;
979       else
980         {
981           DBusAuthState auth_state;
982
983           auth_state = _dbus_auth_do_work (transport->auth);
984
985           /* If we need memory we install the write watch just in case,
986            * if there's no need for it, it will get de-installed
987            * next time we try reading.
988            */
989           if (auth_state == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND ||
990               auth_state == DBUS_AUTH_STATE_WAITING_FOR_MEMORY)
991             needed = TRUE;
992           else
993             needed = FALSE;
994         }
995     }
996
997   _dbus_verbose ("check_write_watch(): needed = %d on connection %p watch %p fd = %d outgoing messages exist %d\n",
998                  needed, transport->connection, socket_transport->write_watch,
999                  socket_transport->fd,
1000                  _dbus_connection_has_messages_to_send_unlocked (transport->connection));
1001
1002   _dbus_connection_toggle_watch_unlocked (transport->connection,
1003                                           socket_transport->write_watch,
1004                                           needed);
1005
1006   _dbus_transport_unref (transport);
1007 }
1008
1009 static void
1010 check_read_watch (DBusTransport *transport)
1011 {
1012   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
1013   dbus_bool_t need_read_watch;
1014
1015   _dbus_verbose ("fd = %d\n",socket_transport->fd);
1016
1017   if (transport->connection == NULL)
1018     return;
1019
1020   if (transport->disconnected)
1021     {
1022       _dbus_assert (socket_transport->read_watch == NULL);
1023       return;
1024     }
1025
1026   _dbus_transport_ref (transport);
1027
1028   if (_dbus_transport_get_is_authenticated (transport))
1029     need_read_watch =
1030       (_dbus_counter_get_size_value (transport->live_messages) < transport->max_live_messages_size) &&
1031       (_dbus_counter_get_unix_fd_value (transport->live_messages) < transport->max_live_messages_unix_fds);
1032   else
1033     {
1034       if (transport->receive_credentials_pending)
1035         need_read_watch = TRUE;
1036       else
1037         {
1038           /* The reason to disable need_read_watch when not WAITING_FOR_INPUT
1039            * is to avoid spinning on the file descriptor when we're waiting
1040            * to write or for some other part of the auth process
1041            */
1042           DBusAuthState auth_state;
1043
1044           auth_state = _dbus_auth_do_work (transport->auth);
1045
1046           /* If we need memory we install the read watch just in case,
1047            * if there's no need for it, it will get de-installed
1048            * next time we try reading. If we're authenticated we
1049            * install it since we normally have it installed while
1050            * authenticated.
1051            */
1052           if (auth_state == DBUS_AUTH_STATE_WAITING_FOR_INPUT ||
1053               auth_state == DBUS_AUTH_STATE_WAITING_FOR_MEMORY ||
1054               auth_state == DBUS_AUTH_STATE_AUTHENTICATED)
1055             need_read_watch = TRUE;
1056           else
1057             need_read_watch = FALSE;
1058         }
1059     }
1060
1061   _dbus_verbose ("  setting read watch enabled = %d\n", need_read_watch);
1062   _dbus_connection_toggle_watch_unlocked (transport->connection,
1063                                           socket_transport->read_watch,
1064                                           need_read_watch);
1065
1066   _dbus_transport_unref (transport);
1067 }
1068
1069 static void
1070 do_io_error (DBusTransport *transport)
1071 {
1072   _dbus_transport_ref (transport);
1073   _dbus_transport_disconnect (transport);
1074   _dbus_transport_unref (transport);
1075 }
1076
1077 /* return value is whether we successfully read any new data. */
1078 static dbus_bool_t
1079 read_data_into_auth (DBusTransport *transport,
1080                      dbus_bool_t   *oom)
1081 {
1082   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
1083   DBusString *buffer;
1084   int bytes_read;
1085
1086   *oom = FALSE;
1087
1088   _dbus_auth_get_buffer (transport->auth, &buffer);
1089
1090   bytes_read = _dbus_read_socket (socket_transport->fd,
1091                                   buffer, socket_transport->max_bytes_read_per_iteration);
1092
1093   _dbus_auth_return_buffer (transport->auth, buffer,
1094                             bytes_read > 0 ? bytes_read : 0);
1095
1096   if (bytes_read > 0)
1097     {
1098       _dbus_verbose (" read %d bytes in auth phase\n", bytes_read);
1099
1100       return TRUE;
1101     }
1102   else if (bytes_read < 0)
1103     {
1104       /* EINTR already handled for us */
1105
1106       if (_dbus_get_is_errno_enomem ())
1107         {
1108           *oom = TRUE;
1109         }
1110       else if (_dbus_get_is_errno_eagain_or_ewouldblock ())
1111         ; /* do nothing, just return FALSE below */
1112       else
1113         {
1114           _dbus_verbose ("Error reading from remote app: %s\n",
1115                          _dbus_strerror_from_errno ());
1116           do_io_error (transport);
1117         }
1118
1119       return FALSE;
1120     }
1121   else
1122     {
1123       _dbus_assert (bytes_read == 0);
1124
1125       _dbus_verbose ("Disconnected from remote app\n");
1126       do_io_error (transport);
1127
1128       return FALSE;
1129     }
1130 }
1131
1132 /* Return value is whether we successfully wrote any bytes */
1133 static dbus_bool_t
1134 write_data_from_auth (DBusTransport *transport)
1135 {
1136   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
1137   int bytes_written;
1138   const DBusString *buffer;
1139
1140   if (!_dbus_auth_get_bytes_to_send (transport->auth,
1141                                      &buffer))
1142     return FALSE;
1143
1144   bytes_written = _dbus_write_socket (socket_transport->fd,
1145                                       buffer,
1146                                       0, _dbus_string_get_length (buffer));
1147
1148   if (bytes_written > 0)
1149     {
1150       _dbus_auth_bytes_sent (transport->auth, bytes_written);
1151       return TRUE;
1152     }
1153   else if (bytes_written < 0)
1154     {
1155       /* EINTR already handled for us */
1156
1157       if (_dbus_get_is_errno_eagain_or_ewouldblock ())
1158         ;
1159       else
1160         {
1161           _dbus_verbose ("Error writing to remote app: %s\n",
1162                          _dbus_strerror_from_errno ());
1163           do_io_error (transport);
1164         }
1165     }
1166
1167   return FALSE;
1168 }
1169
1170 /* FALSE on OOM */
1171 static dbus_bool_t
1172 exchange_credentials (DBusTransport *transport,
1173                       dbus_bool_t    do_reading,
1174                       dbus_bool_t    do_writing)
1175 {
1176   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
1177   DBusError error = DBUS_ERROR_INIT;
1178
1179   _dbus_verbose ("exchange_credentials: do_reading = %d, do_writing = %d\n",
1180                   do_reading, do_writing);
1181
1182   if (do_writing && transport->send_credentials_pending)
1183     {
1184       if (_dbus_send_credentials_socket (socket_transport->fd,
1185                                          &error))
1186         {
1187           transport->send_credentials_pending = FALSE;
1188         }
1189       else
1190         {
1191           _dbus_verbose ("Failed to write credentials: %s\n", error.message);
1192           dbus_error_free (&error);
1193           do_io_error (transport);
1194         }
1195     }
1196
1197   if (do_reading && transport->receive_credentials_pending)
1198     {
1199       /* FIXME this can fail due to IO error _or_ OOM, broken
1200        * (somewhat tricky to fix since the OOM error can be set after
1201        * we already read the credentials byte, so basically we need to
1202        * separate reading the byte and storing it in the
1203        * transport->credentials). Does not really matter for now
1204        * because storing in credentials never actually fails on unix.
1205        */
1206       if (_dbus_read_credentials_socket (socket_transport->fd,
1207                                          transport->credentials,
1208                                          &error))
1209         {
1210           transport->receive_credentials_pending = FALSE;
1211         }
1212       else
1213         {
1214           _dbus_verbose ("Failed to read credentials %s\n", error.message);
1215           dbus_error_free (&error);
1216           do_io_error (transport);
1217         }
1218     }
1219
1220   if (!(transport->send_credentials_pending ||
1221         transport->receive_credentials_pending))
1222     {
1223       if (!_dbus_auth_set_credentials (transport->auth,
1224                                        transport->credentials))
1225         return FALSE;
1226     }
1227
1228   return TRUE;
1229 }
1230
1231 static dbus_bool_t
1232 do_authentication (DBusTransport *transport,
1233                    dbus_bool_t    do_reading,
1234                    dbus_bool_t    do_writing,
1235                    dbus_bool_t   *auth_completed)
1236 {
1237   dbus_bool_t oom;
1238   dbus_bool_t orig_auth_state;
1239
1240   oom = FALSE;
1241
1242   orig_auth_state = _dbus_transport_get_is_authenticated (transport);
1243
1244   /* This is essential to avoid the check_write_watch() at the end,
1245    * we don't want to add a write watch in do_iteration before
1246    * we try writing and get EAGAIN
1247    */
1248   if (orig_auth_state)
1249     {
1250       if (auth_completed)
1251         *auth_completed = FALSE;
1252       return TRUE;
1253     }
1254
1255   _dbus_transport_ref (transport);
1256
1257   while (!_dbus_transport_get_is_authenticated (transport) &&
1258          _dbus_transport_get_is_connected (transport))
1259     {
1260       if (!exchange_credentials (transport, do_reading, do_writing))
1261         {
1262           /* OOM */
1263           oom = TRUE;
1264           goto out;
1265         }
1266
1267       if (transport->send_credentials_pending ||
1268           transport->receive_credentials_pending)
1269         {
1270           _dbus_verbose ("send_credentials_pending = %d receive_credentials_pending = %d\n",
1271                          transport->send_credentials_pending,
1272                          transport->receive_credentials_pending);
1273           goto out;
1274         }
1275
1276 #define TRANSPORT_SIDE(t) ((t)->is_server ? "server" : "client")
1277       switch (_dbus_auth_do_work (transport->auth))
1278         {
1279         case DBUS_AUTH_STATE_WAITING_FOR_INPUT:
1280           _dbus_verbose (" %s auth state: waiting for input\n",
1281                          TRANSPORT_SIDE (transport));
1282           if (!do_reading || !read_data_into_auth (transport, &oom))
1283             goto out;
1284           break;
1285
1286         case DBUS_AUTH_STATE_WAITING_FOR_MEMORY:
1287           _dbus_verbose (" %s auth state: waiting for memory\n",
1288                          TRANSPORT_SIDE (transport));
1289           oom = TRUE;
1290           goto out;
1291           break;
1292
1293         case DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND:
1294           _dbus_verbose (" %s auth state: bytes to send\n",
1295                          TRANSPORT_SIDE (transport));
1296           if (!do_writing || !write_data_from_auth (transport))
1297             goto out;
1298           break;
1299
1300         case DBUS_AUTH_STATE_NEED_DISCONNECT:
1301           _dbus_verbose (" %s auth state: need to disconnect\n",
1302                          TRANSPORT_SIDE (transport));
1303           do_io_error (transport);
1304           break;
1305
1306         case DBUS_AUTH_STATE_AUTHENTICATED:
1307           _dbus_verbose (" %s auth state: authenticated\n",
1308                          TRANSPORT_SIDE (transport));
1309           break;
1310         }
1311     }
1312
1313  out:
1314   if (auth_completed)
1315     *auth_completed = (orig_auth_state != _dbus_transport_get_is_authenticated (transport));
1316
1317   check_read_watch (transport);
1318   check_write_watch (transport);
1319   _dbus_transport_unref (transport);
1320
1321   if (oom)
1322     return FALSE;
1323   else
1324     return TRUE;
1325 }
1326
1327 /* returns false on oom */
1328 static dbus_bool_t
1329 do_writing (DBusTransport *transport)
1330 {
1331         int total;
1332         DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
1333         dbus_bool_t oom;
1334
1335         /* No messages without authentication! */
1336         if (!_dbus_transport_get_is_authenticated (transport))
1337     {
1338                 _dbus_verbose ("Not authenticated, not writing anything\n");
1339                 return TRUE;
1340     }
1341
1342         if (transport->disconnected)
1343     {
1344                 _dbus_verbose ("Not connected, not writing anything\n");
1345                 return TRUE;
1346     }
1347
1348 #if 1
1349         _dbus_verbose ("do_writing(), have_messages = %d, fd = %d\n",
1350                  _dbus_connection_has_messages_to_send_unlocked (transport->connection),
1351                  socket_transport->fd);
1352 #endif
1353
1354         oom = FALSE;
1355         total = 0;
1356
1357         while (!transport->disconnected && _dbus_connection_has_messages_to_send_unlocked (transport->connection))
1358     {
1359                 int bytes_written;
1360                 DBusMessage *message;
1361                 const DBusString *header;
1362                 const DBusString *body;
1363                 int total_bytes_to_write;
1364
1365
1366                 if (total > socket_transport->max_bytes_written_per_iteration)
1367         {
1368                         _dbus_verbose ("%d bytes exceeds %d bytes written per iteration, returning\n",
1369                          total, socket_transport->max_bytes_written_per_iteration);
1370                         goto out;
1371         }
1372
1373                 message = _dbus_connection_get_message_to_send (transport->connection);
1374                 _dbus_assert (message != NULL);
1375                 dbus_message_lock (message);
1376                 _dbus_message_get_network_data (message, &header, &body);
1377
1378                 if (_dbus_auth_needs_encoding (transport->auth))
1379         {
1380                         // Does fd passing even make sense with encoded data?
1381                         _dbus_assert(!DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport));
1382
1383                         if (_dbus_string_get_length (&socket_transport->encoded_outgoing) == 0)
1384             {
1385                                 if (!_dbus_auth_encode_data (transport->auth,
1386                                            header, &socket_transport->encoded_outgoing))
1387                 {
1388                                         oom = TRUE;
1389                                         goto out;
1390                 }
1391
1392                                 if (!_dbus_auth_encode_data (transport->auth,
1393                                            body, &socket_transport->encoded_outgoing))
1394                 {
1395                                         _dbus_string_set_length (&socket_transport->encoded_outgoing, 0);
1396                                         oom = TRUE;
1397                                         goto out;
1398                 }
1399             }
1400
1401                         total_bytes_to_write = _dbus_string_get_length (&socket_transport->encoded_outgoing);
1402                         bytes_written = kdbus_write_msg_encoded(message, socket_transport);
1403         }
1404                 else
1405                 {
1406                         total_bytes_to_write = _dbus_string_get_length(header) + _dbus_string_get_length(body);
1407                         bytes_written = kdbus_write_msg(transport->connection, message, socket_transport->fd);
1408                 }
1409
1410                 if (bytes_written < 0)
1411                 {
1412                         /* EINTR already handled for us */
1413
1414           /* For some discussion of why we also ignore EPIPE here, see
1415            * http://lists.freedesktop.org/archives/dbus/2008-March/009526.html
1416            */
1417
1418                         if (_dbus_get_is_errno_eagain_or_ewouldblock () || _dbus_get_is_errno_epipe ())
1419                                 goto out;
1420                         else
1421                         {
1422                                 _dbus_verbose ("Error writing to remote app: %s\n",
1423                                                          _dbus_strerror_from_errno ());
1424                                 do_io_error (transport);
1425                                 goto out;
1426                         }
1427                 }
1428                 else
1429                 {
1430                         _dbus_verbose (" wrote %d bytes of %d\n", bytes_written,
1431                          total_bytes_to_write);
1432
1433                         total += bytes_written;
1434                         socket_transport->message_bytes_written += bytes_written;
1435
1436                         _dbus_assert (socket_transport->message_bytes_written <=
1437                         total_bytes_to_write);
1438
1439                           if (socket_transport->message_bytes_written == total_bytes_to_write)
1440                           {
1441                                   socket_transport->message_bytes_written = 0;
1442                                   _dbus_string_set_length (&socket_transport->encoded_outgoing, 0);
1443                                   _dbus_string_compact (&socket_transport->encoded_outgoing, 2048);
1444
1445                                   _dbus_connection_message_sent_unlocked (transport->connection,
1446                                                                                                                   message);
1447                           }
1448                 }
1449     }
1450
1451         out:
1452         if (oom)
1453                 return FALSE;
1454         else
1455                 return TRUE;
1456 }
1457
1458 /* returns false on out-of-memory */
1459 static dbus_bool_t
1460 do_reading (DBusTransport *transport)
1461 {
1462   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
1463   DBusString *buffer;
1464   int bytes_read;
1465   int total;
1466   dbus_bool_t oom;
1467
1468   _dbus_verbose ("fd = %d\n",socket_transport->fd);
1469
1470   /* No messages without authentication! */
1471   if (!_dbus_transport_get_is_authenticated (transport))
1472     return TRUE;
1473
1474   oom = FALSE;
1475
1476   total = 0;
1477
1478  again:
1479
1480   /* See if we've exceeded max messages and need to disable reading */
1481   check_read_watch (transport);
1482
1483   if (total > socket_transport->max_bytes_read_per_iteration)
1484     {
1485       _dbus_verbose ("%d bytes exceeds %d bytes read per iteration, returning\n",
1486                      total, socket_transport->max_bytes_read_per_iteration);
1487       goto out;
1488     }
1489
1490   _dbus_assert (socket_transport->read_watch != NULL ||
1491                 transport->disconnected);
1492
1493   if (transport->disconnected)
1494     goto out;
1495
1496   if (!dbus_watch_get_enabled (socket_transport->read_watch))
1497     return TRUE;
1498
1499   if (_dbus_auth_needs_decoding (transport->auth))
1500     {
1501       /* Does fd passing even make sense with encoded data? */
1502     /*  _dbus_assert(!DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport));
1503
1504       if (_dbus_string_get_length (&socket_transport->encoded_incoming) > 0)
1505         bytes_read = _dbus_string_get_length (&socket_transport->encoded_incoming);
1506       else
1507         bytes_read = _dbus_read_socket (socket_transport->fd,
1508                                         &socket_transport->encoded_incoming,
1509                                         socket_transport->max_bytes_read_per_iteration);*/
1510
1511           bytes_read = kdbus_read_message(socket_transport,  &socket_transport->encoded_incoming);
1512
1513       _dbus_assert (_dbus_string_get_length (&socket_transport->encoded_incoming) ==
1514                     bytes_read);
1515
1516       if (bytes_read > 0)
1517         {
1518           int orig_len;
1519
1520           _dbus_message_loader_get_buffer (transport->loader,
1521                                            &buffer);
1522
1523           orig_len = _dbus_string_get_length (buffer);
1524
1525           if (!_dbus_auth_decode_data (transport->auth,
1526                                        &socket_transport->encoded_incoming,
1527                                        buffer))
1528             {
1529               _dbus_verbose ("Out of memory decoding incoming data\n");
1530               _dbus_message_loader_return_buffer (transport->loader,
1531                                               buffer,
1532                                               _dbus_string_get_length (buffer) - orig_len);
1533
1534               oom = TRUE;
1535               goto out;
1536             }
1537
1538           _dbus_message_loader_return_buffer (transport->loader,
1539                                               buffer,
1540                                               _dbus_string_get_length (buffer) - orig_len);
1541
1542           _dbus_string_set_length (&socket_transport->encoded_incoming, 0);
1543           _dbus_string_compact (&socket_transport->encoded_incoming, 2048);
1544         }
1545     }
1546   else
1547     {
1548       _dbus_message_loader_get_buffer (transport->loader,
1549                                        &buffer);
1550
1551       bytes_read = kdbus_read_message(socket_transport, buffer);
1552
1553       _dbus_message_loader_return_buffer (transport->loader,
1554                                           buffer,
1555                                           bytes_read < 0 ? 0 : bytes_read);
1556     }
1557
1558   if (bytes_read < 0)
1559     {
1560       /* EINTR already handled for us */
1561
1562       if (_dbus_get_is_errno_enomem ())
1563         {
1564           _dbus_verbose ("Out of memory in read()/do_reading()\n");
1565           oom = TRUE;
1566           goto out;
1567         }
1568       else if (_dbus_get_is_errno_eagain_or_ewouldblock ())
1569         goto out;
1570       else
1571         {
1572           _dbus_verbose ("Error reading from remote app: %s\n",
1573                          _dbus_strerror_from_errno ());
1574           do_io_error (transport);
1575           goto out;
1576         }
1577     }
1578   else if (bytes_read == 0)
1579     {
1580       _dbus_verbose ("Disconnected from remote app\n");
1581       do_io_error (transport);
1582       goto out;
1583     }
1584   else
1585     {
1586       _dbus_verbose (" read %d bytes\n", bytes_read);
1587
1588       total += bytes_read;
1589
1590       if (!_dbus_transport_queue_messages (transport))
1591         {
1592           oom = TRUE;
1593           _dbus_verbose (" out of memory when queueing messages we just read in the transport\n");
1594           goto out;
1595         }
1596
1597       /* Try reading more data until we get EAGAIN and return, or
1598        * exceed max bytes per iteration.  If in blocking mode of
1599        * course we'll block instead of returning.
1600        */
1601       goto again;
1602     }
1603
1604  out:
1605   if (oom)
1606     return FALSE;
1607   else
1608     return TRUE;
1609 }
1610
1611 static dbus_bool_t
1612 unix_error_with_read_to_come (DBusTransport *itransport,
1613                               DBusWatch     *watch,
1614                               unsigned int   flags)
1615 {
1616   DBusTransportSocket *transport = (DBusTransportSocket *) itransport;
1617
1618   if (!(flags & DBUS_WATCH_HANGUP || flags & DBUS_WATCH_ERROR))
1619     return FALSE;
1620
1621   /* If we have a read watch enabled ...
1622      we -might have data incoming ... => handle the HANGUP there */
1623   if (watch != transport->read_watch &&
1624       _dbus_watch_get_enabled (transport->read_watch))
1625     return FALSE;
1626
1627   return TRUE;
1628 }
1629
1630 static dbus_bool_t
1631 socket_handle_watch (DBusTransport *transport,
1632                    DBusWatch     *watch,
1633                    unsigned int   flags)
1634 {
1635   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
1636
1637   _dbus_assert (watch == socket_transport->read_watch ||
1638                 watch == socket_transport->write_watch);
1639   _dbus_assert (watch != NULL);
1640
1641   /* If we hit an error here on a write watch, don't disconnect the transport yet because data can
1642    * still be in the buffer and do_reading may need several iteration to read
1643    * it all (because of its max_bytes_read_per_iteration limit).
1644    */
1645   if (!(flags & DBUS_WATCH_READABLE) && unix_error_with_read_to_come (transport, watch, flags))
1646     {
1647       _dbus_verbose ("Hang up or error on watch\n");
1648       _dbus_transport_disconnect (transport);
1649       return TRUE;
1650     }
1651
1652   if (watch == socket_transport->read_watch &&
1653       (flags & DBUS_WATCH_READABLE))
1654     {
1655       dbus_bool_t auth_finished;
1656 #if 1
1657       _dbus_verbose ("handling read watch %p flags = %x\n",
1658                      watch, flags);
1659 #endif
1660       if (!do_authentication (transport, TRUE, FALSE, &auth_finished))
1661         return FALSE;
1662
1663       /* We don't want to do a read immediately following
1664        * a successful authentication.  This is so we
1665        * have a chance to propagate the authentication
1666        * state further up.  Specifically, we need to
1667        * process any pending data from the auth object.
1668        */
1669       if (!auth_finished)
1670         {
1671           if (!do_reading (transport))
1672             {
1673               _dbus_verbose ("no memory to read\n");
1674               return FALSE;
1675             }
1676         }
1677       else
1678         {
1679           _dbus_verbose ("Not reading anything since we just completed the authentication\n");
1680         }
1681     }
1682   else if (watch == socket_transport->write_watch &&
1683            (flags & DBUS_WATCH_WRITABLE))
1684     {
1685 #if 1
1686       _dbus_verbose ("handling write watch, have_outgoing_messages = %d\n",
1687                      _dbus_connection_has_messages_to_send_unlocked (transport->connection));
1688 #endif
1689       if (!do_authentication (transport, FALSE, TRUE, NULL))
1690         return FALSE;
1691
1692       if (!do_writing (transport))
1693         {
1694           _dbus_verbose ("no memory to write\n");
1695           return FALSE;
1696         }
1697
1698       /* See if we still need the write watch */
1699       check_write_watch (transport);
1700     }
1701 #ifdef DBUS_ENABLE_VERBOSE_MODE
1702   else
1703     {
1704       if (watch == socket_transport->read_watch)
1705         _dbus_verbose ("asked to handle read watch with non-read condition 0x%x\n",
1706                        flags);
1707       else if (watch == socket_transport->write_watch)
1708         _dbus_verbose ("asked to handle write watch with non-write condition 0x%x\n",
1709                        flags);
1710       else
1711         _dbus_verbose ("asked to handle watch %p on fd %d that we don't recognize\n",
1712                        watch, dbus_watch_get_socket (watch));
1713     }
1714 #endif /* DBUS_ENABLE_VERBOSE_MODE */
1715
1716   return TRUE;
1717 }
1718
1719 static void
1720 socket_disconnect (DBusTransport *transport)
1721 {
1722   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
1723
1724   _dbus_verbose ("\n");
1725
1726   free_watches (transport);
1727
1728   _dbus_close_socket (socket_transport->fd, NULL);
1729   socket_transport->fd = -1;
1730 }
1731
1732 static dbus_bool_t
1733 socket_connection_set (DBusTransport *transport)
1734 {
1735   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
1736
1737   _dbus_watch_set_handler (socket_transport->write_watch,
1738                            _dbus_connection_handle_watch,
1739                            transport->connection, NULL);
1740
1741   _dbus_watch_set_handler (socket_transport->read_watch,
1742                            _dbus_connection_handle_watch,
1743                            transport->connection, NULL);
1744
1745   if (!_dbus_connection_add_watch_unlocked (transport->connection,
1746                                             socket_transport->write_watch))
1747     return FALSE;
1748
1749   if (!_dbus_connection_add_watch_unlocked (transport->connection,
1750                                             socket_transport->read_watch))
1751     {
1752       _dbus_connection_remove_watch_unlocked (transport->connection,
1753                                               socket_transport->write_watch);
1754       return FALSE;
1755     }
1756
1757   check_read_watch (transport);
1758   check_write_watch (transport);
1759
1760   return TRUE;
1761 }
1762
1763 /**
1764  * @todo We need to have a way to wake up the select sleep if
1765  * a new iteration request comes in with a flag (read/write) that
1766  * we're not currently serving. Otherwise a call that just reads
1767  * could block a write call forever (if there are no incoming
1768  * messages).
1769  */
1770 static  void
1771 kdbus_do_iteration (DBusTransport *transport,
1772                    unsigned int   flags,
1773                    int            timeout_milliseconds)
1774 {
1775         DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
1776         DBusPollFD poll_fd;
1777         int poll_res;
1778         int poll_timeout;
1779
1780         _dbus_verbose (" iteration flags = %s%s timeout = %d read_watch = %p write_watch = %p fd = %d\n",
1781                  flags & DBUS_ITERATION_DO_READING ? "read" : "",
1782                  flags & DBUS_ITERATION_DO_WRITING ? "write" : "",
1783                  timeout_milliseconds,
1784                  socket_transport->read_watch,
1785                  socket_transport->write_watch,
1786                  socket_transport->fd);
1787
1788   /* the passed in DO_READING/DO_WRITING flags indicate whether to
1789    * read/write messages, but regardless of those we may need to block
1790    * for reading/writing to do auth.  But if we do reading for auth,
1791    * we don't want to read any messages yet if not given DO_READING.
1792    */
1793
1794   poll_fd.fd = socket_transport->fd;
1795   poll_fd.events = 0;
1796
1797   if (_dbus_transport_get_is_authenticated (transport))
1798     {
1799       /* This is kind of a hack; if we have stuff to write, then try
1800        * to avoid the poll. This is probably about a 5% speedup on an
1801        * echo client/server.
1802        *
1803        * If both reading and writing were requested, we want to avoid this
1804        * since it could have funky effects:
1805        *   - both ends spinning waiting for the other one to read
1806        *     data so they can finish writing
1807        *   - prioritizing all writing ahead of reading
1808        */
1809       if ((flags & DBUS_ITERATION_DO_WRITING) &&
1810           !(flags & (DBUS_ITERATION_DO_READING | DBUS_ITERATION_BLOCK)) &&
1811           !transport->disconnected &&
1812           _dbus_connection_has_messages_to_send_unlocked (transport->connection))
1813         {
1814           do_writing (transport);
1815
1816           if (transport->disconnected ||
1817               !_dbus_connection_has_messages_to_send_unlocked (transport->connection))
1818             goto out;
1819         }
1820
1821       /* If we get here, we decided to do the poll() after all */
1822       _dbus_assert (socket_transport->read_watch);
1823       if (flags & DBUS_ITERATION_DO_READING)
1824         poll_fd.events |= _DBUS_POLLIN;
1825
1826       _dbus_assert (socket_transport->write_watch);
1827       if (flags & DBUS_ITERATION_DO_WRITING)
1828         poll_fd.events |= _DBUS_POLLOUT;
1829     }
1830   else
1831     {
1832       DBusAuthState auth_state;
1833
1834       auth_state = _dbus_auth_do_work (transport->auth);
1835
1836       if (transport->receive_credentials_pending ||
1837           auth_state == DBUS_AUTH_STATE_WAITING_FOR_INPUT)
1838         poll_fd.events |= _DBUS_POLLIN;
1839
1840       if (transport->send_credentials_pending ||
1841           auth_state == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND)
1842         poll_fd.events |= _DBUS_POLLOUT;
1843     }
1844
1845   if (poll_fd.events)
1846     {
1847       if (flags & DBUS_ITERATION_BLOCK)
1848         poll_timeout = timeout_milliseconds;
1849       else
1850         poll_timeout = 0;
1851
1852       /* For blocking selects we drop the connection lock here
1853        * to avoid blocking out connection access during a potentially
1854        * indefinite blocking call. The io path is still protected
1855        * by the io_path_cond condvar, so we won't reenter this.
1856        */
1857       if (flags & DBUS_ITERATION_BLOCK)
1858         {
1859           _dbus_verbose ("unlock pre poll\n");
1860           _dbus_connection_unlock (transport->connection);
1861         }
1862       _dbus_verbose ("poll_fd.events: %x, timeout: %d\n", poll_fd.events, poll_timeout);
1863     again:
1864       poll_res = _dbus_poll (&poll_fd, 1, poll_timeout);
1865
1866       if (poll_res < 0 && _dbus_get_is_errno_eintr ())
1867       {
1868           _dbus_verbose ("Error from _dbus_poll(): %s\n",
1869                          _dbus_strerror_from_errno ());
1870           goto again;
1871       }
1872       _dbus_verbose ("poll_fd.revents: %x\n", poll_fd.revents);
1873
1874     /*  poll_res = poll_timeout;                        // todo temporary walkaround of above problem
1875       poll_res = 1;                                                     // todo temporary walkaround of above problem
1876       poll_fd.revents = poll_fd.events;    // todo temporary walkaround of above problem*/
1877
1878       if (flags & DBUS_ITERATION_BLOCK)
1879         {
1880           _dbus_verbose ("lock post poll\n");
1881           _dbus_connection_lock (transport->connection);
1882         }
1883
1884       if (poll_res >= 0)
1885         {
1886           if (poll_res == 0)
1887             poll_fd.revents = 0; /* some concern that posix does not guarantee this;
1888                                   * valgrind flags it as an error. though it probably
1889                                   * is guaranteed on linux at least.
1890                                   */
1891
1892           if (poll_fd.revents & _DBUS_POLLERR)
1893             do_io_error (transport);
1894           else
1895             {
1896               dbus_bool_t need_read = (poll_fd.revents & _DBUS_POLLIN) > 0;
1897               dbus_bool_t need_write = (poll_fd.revents & _DBUS_POLLOUT) > 0;
1898               dbus_bool_t authentication_completed;
1899
1900               _dbus_verbose ("in iteration, need_read=%d need_write=%d\n",
1901                              need_read, need_write);
1902               do_authentication (transport, need_read, need_write,
1903                                  &authentication_completed);
1904
1905               /* See comment in socket_handle_watch. */
1906               if (authentication_completed)
1907                 goto out;
1908
1909               if (need_read && (flags & DBUS_ITERATION_DO_READING))
1910                 do_reading (transport);
1911               if (need_write && (flags & DBUS_ITERATION_DO_WRITING))
1912                 do_writing (transport);
1913             }
1914         }
1915       else
1916         {
1917           _dbus_verbose ("Error from _dbus_poll(): %s\n",
1918                          _dbus_strerror_from_errno ());
1919         }
1920     }
1921
1922
1923  out:
1924   /* We need to install the write watch only if we did not
1925    * successfully write everything. Note we need to be careful that we
1926    * don't call check_write_watch *before* do_writing, since it's
1927    * inefficient to add the write watch, and we can avoid it most of
1928    * the time since we can write immediately.
1929    *
1930    * However, we MUST always call check_write_watch(); DBusConnection code
1931    * relies on the fact that running an iteration will notice that
1932    * messages are pending.
1933    */
1934   check_write_watch (transport);
1935
1936   _dbus_verbose (" ... leaving do_iteration()\n");
1937 }
1938
1939 static void
1940 socket_live_messages_changed (DBusTransport *transport)
1941 {
1942   /* See if we should look for incoming messages again */
1943   check_read_watch (transport);
1944 }
1945
1946 static const DBusTransportVTable kdbus_vtable = {
1947   socket_finalize,
1948   socket_handle_watch,
1949   socket_disconnect,
1950   socket_connection_set,
1951   kdbus_do_iteration,
1952   socket_live_messages_changed,
1953   socket_get_socket_fd
1954 };
1955
1956 /**
1957  * Creates a new transport for the given kdbus file descriptor.  The file
1958  * descriptor must be nonblocking (use _dbus_set_fd_nonblocking() to
1959  * make it so).
1960  *
1961  * @param fd the file descriptor.
1962  * @param server_guid non-#NULL if this transport is on the server side of a connection
1963  * @param address the transport's address
1964  * @returns the new transport, or #NULL if no memory.
1965  */
1966 static DBusTransport*
1967 _dbus_transport_new_for_socket_kdbus (int       fd,
1968                                           const DBusString *server_guid,
1969                                           const DBusString *address)
1970 {
1971         DBusTransportSocket *socket_transport;
1972
1973   socket_transport = dbus_new0 (DBusTransportSocket, 1);
1974   if (socket_transport == NULL)
1975     return NULL;
1976
1977   if (!_dbus_string_init (&socket_transport->encoded_outgoing))
1978     goto failed_0;
1979
1980   if (!_dbus_string_init (&socket_transport->encoded_incoming))
1981     goto failed_1;
1982
1983   socket_transport->write_watch = _dbus_watch_new (fd,
1984                                                  DBUS_WATCH_WRITABLE,
1985                                                  FALSE,
1986                                                  NULL, NULL, NULL);
1987   if (socket_transport->write_watch == NULL)
1988     goto failed_2;
1989
1990   socket_transport->read_watch = _dbus_watch_new (fd,
1991                                                 DBUS_WATCH_READABLE,
1992                                                 FALSE,
1993                                                 NULL, NULL, NULL);
1994   if (socket_transport->read_watch == NULL)
1995     goto failed_3;
1996
1997   if (!_dbus_transport_init_base (&socket_transport->base,
1998                                   &kdbus_vtable,
1999                                   server_guid, address))
2000     goto failed_4;
2001
2002 #ifdef HAVE_UNIX_FD_PASSING
2003   _dbus_auth_set_unix_fd_possible(socket_transport->base.auth, _dbus_socket_can_pass_unix_fd(fd));
2004 #endif
2005
2006   socket_transport->fd = fd;
2007   socket_transport->message_bytes_written = 0;
2008
2009   /* These values should probably be tunable or something. */
2010   socket_transport->max_bytes_read_per_iteration = POOL_SIZE;
2011   socket_transport->max_bytes_written_per_iteration = 2048;
2012
2013   socket_transport->kdbus_mmap_ptr = NULL;
2014
2015   return (DBusTransport*) socket_transport;
2016
2017  failed_4:
2018   _dbus_watch_invalidate (socket_transport->read_watch);
2019   _dbus_watch_unref (socket_transport->read_watch);
2020  failed_3:
2021   _dbus_watch_invalidate (socket_transport->write_watch);
2022   _dbus_watch_unref (socket_transport->write_watch);
2023  failed_2:
2024   _dbus_string_free (&socket_transport->encoded_incoming);
2025  failed_1:
2026   _dbus_string_free (&socket_transport->encoded_outgoing);
2027  failed_0:
2028   dbus_free (socket_transport);
2029   return NULL;
2030 }
2031
2032
2033 /**
2034  * Creates a connection to the kdbus bus
2035   *
2036  * This will set FD_CLOEXEC for the socket returned.
2037  *
2038  * @param path the path to UNIX domain socket
2039  * @param error return location for error code
2040  * @returns connection file descriptor or -1 on error
2041  */
2042 static int _dbus_connect_kdbus (const char *path, DBusError *error)
2043 {
2044         int fd;
2045
2046         _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2047         _dbus_verbose ("connecting to kdbus bus %s\n", path);
2048
2049         fd = open(path, O_RDWR|O_CLOEXEC|O_NONBLOCK); //[RP] | O_NONBLOCK added here, in dbus added separately in section commented out below
2050         if (fd < 0)
2051         {
2052                 dbus_set_error(error, _dbus_error_from_errno (errno), "Failed to open file descriptor: %s", _dbus_strerror (errno));
2053                 _DBUS_ASSERT_ERROR_IS_SET(error);
2054                 return -1;  //[RP] not needed here if commented block below is removed
2055         }
2056
2057         /*if (!_dbus_set_fd_nonblocking (fd, error))
2058     {
2059                 _DBUS_ASSERT_ERROR_IS_SET (error);
2060                 _dbus_close (fd, NULL);
2061                 return -1;
2062     }*/
2063
2064         return fd;
2065 }
2066
2067 static dbus_bool_t kdbus_mmap(DBusTransport* transport)
2068 {
2069         DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
2070
2071         socket_transport->kdbus_mmap_ptr = mmap(NULL, POOL_SIZE, PROT_READ, MAP_SHARED, socket_transport->fd, 0);
2072         if (socket_transport->kdbus_mmap_ptr == MAP_FAILED)
2073                 return FALSE;
2074
2075         return TRUE;
2076 }
2077
2078 /**
2079  * Creates a new transport for kdbus.
2080  * This creates a client-side of a transport.
2081  *
2082  * @param path the path to the domain socket.
2083  * @param error address where an error can be returned.
2084  * @returns a new transport, or #NULL on failure.
2085  */
2086 static DBusTransport* _dbus_transport_new_for_kdbus (const char *path, DBusError *error)
2087 {
2088         int fd;
2089         DBusTransport *transport;
2090         DBusString address;
2091
2092         _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2093
2094         if (!_dbus_string_init (&address))
2095     {
2096                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2097                 return NULL;
2098     }
2099
2100         fd = -1;
2101
2102         if ((!_dbus_string_append (&address, "kdbus:path=")) || (!_dbus_string_append (&address, path)))
2103     {
2104                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2105                 goto failed_0;
2106     }
2107
2108         fd = _dbus_connect_kdbus (path, error);
2109         if (fd < 0)
2110     {
2111                 _DBUS_ASSERT_ERROR_IS_SET (error);
2112                 goto failed_0;
2113     }
2114
2115         _dbus_verbose ("Successfully connected to kdbus bus %s\n", path);
2116
2117         transport = _dbus_transport_new_for_socket_kdbus (fd, NULL, &address);
2118         if (transport == NULL)
2119     {
2120                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2121                 goto failed_1;
2122     }
2123
2124         _dbus_string_free (&address);
2125
2126         return transport;
2127
2128         failed_1:
2129                 _dbus_close_socket (fd, NULL);
2130         failed_0:
2131                 _dbus_string_free (&address);
2132         return NULL;
2133 }
2134
2135
2136 /**
2137  * Opens kdbus transport.
2138  *
2139  * @param entry the address entry to try opening
2140  * @param transport_p return location for the opened transport
2141  * @param error error to be set
2142  * @returns result of the attempt
2143  */
2144 DBusTransportOpenResult _dbus_transport_open_kdbus(DBusAddressEntry  *entry,
2145                                                            DBusTransport    **transport_p,
2146                                                            DBusError         *error)
2147 {
2148         const char *method;
2149
2150         method = dbus_address_entry_get_method (entry);
2151         _dbus_assert (method != NULL);
2152
2153         if (strcmp (method, "kdbus") == 0)
2154     {
2155                 const char *path = dbus_address_entry_get_value (entry, "path");
2156
2157                 if (path == NULL)
2158         {
2159                         _dbus_set_bad_address (error, "kdbus", "path", NULL);
2160                         return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
2161         }
2162
2163         *transport_p = _dbus_transport_new_for_kdbus (path, error);
2164
2165         if (*transport_p == NULL)
2166         {
2167                 _DBUS_ASSERT_ERROR_IS_SET (error);
2168                 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
2169         }
2170         else
2171         {
2172                 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2173                 return DBUS_TRANSPORT_OPEN_OK;
2174         }
2175     }
2176         else
2177     {
2178                 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2179                 return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
2180     }
2181 }
2182
2183 static struct kdbus_policy *make_policy_name(const char *name)
2184 {
2185         struct kdbus_policy *p;
2186         __u64 size;
2187
2188         size = offsetof(struct kdbus_policy, name) + strlen(name) + 1;
2189         p = malloc(size);
2190         if (!p)
2191                 return NULL;
2192         memset(p, 0, size);
2193         p->size = size;
2194         p->type = KDBUS_POLICY_NAME;
2195         strcpy(p->name, name);
2196
2197         return p;
2198 }
2199
2200 static struct kdbus_policy *make_policy_access(__u64 type, __u64 bits, __u64 id)
2201 {
2202         struct kdbus_policy *p;
2203         __u64 size = sizeof(*p);
2204
2205         p = malloc(size);
2206         if (!p)
2207                 return NULL;
2208
2209         memset(p, 0, size);
2210         p->size = size;
2211         p->type = KDBUS_POLICY_ACCESS;
2212         p->access.type = type;
2213         p->access.bits = bits;
2214         p->access.id = id;
2215
2216         return p;
2217 }
2218
2219 static void append_policy(struct kdbus_cmd_policy *cmd_policy, struct kdbus_policy *policy, __u64 max_size)
2220 {
2221         struct kdbus_policy *dst = (struct kdbus_policy *) ((char *) cmd_policy + cmd_policy->size);
2222
2223         if (cmd_policy->size + policy->size > max_size)
2224                 return;
2225
2226         memcpy(dst, policy, policy->size);
2227         cmd_policy->size += KDBUS_ALIGN8(policy->size);
2228         free(policy);
2229 }
2230
2231 dbus_bool_t bus_register_policy_kdbus(const char* name, DBusConnection *connection, DBusError *error)
2232 {
2233         struct kdbus_cmd_policy *cmd_policy;
2234         struct kdbus_policy *policy;
2235         int size = 0xffff;
2236         int fd;
2237
2238         if(!dbus_connection_get_socket(connection, &fd))
2239         {
2240                 dbus_set_error (error, "Failed to get fd for registering policy", NULL);
2241                 return FALSE;
2242         }
2243
2244         cmd_policy = (struct kdbus_cmd_policy *) alloca(size);
2245         memset(cmd_policy, 0, size);
2246
2247         policy = (struct kdbus_policy *) cmd_policy->policies;
2248         cmd_policy->size = offsetof(struct kdbus_cmd_policy, policies);
2249
2250         policy = make_policy_name(name);                //todo to be verified or changed when meaning will be known
2251         append_policy(cmd_policy, policy, size);
2252
2253         policy = make_policy_access(KDBUS_POLICY_ACCESS_USER, KDBUS_POLICY_OWN, getuid());
2254         append_policy(cmd_policy, policy, size);
2255
2256         policy = make_policy_access(KDBUS_POLICY_ACCESS_WORLD, KDBUS_POLICY_RECV, 0);
2257         append_policy(cmd_policy, policy, size);
2258
2259         policy = make_policy_access(KDBUS_POLICY_ACCESS_WORLD, KDBUS_POLICY_SEND, 0);
2260         append_policy(cmd_policy, policy, size);
2261
2262         if (ioctl(fd, KDBUS_CMD_EP_POLICY_SET, cmd_policy) < 0)
2263         {
2264                 dbus_set_error(error,_dbus_error_from_errno (errno), "Error setting EP policy: %s", _dbus_strerror (errno));
2265                 return FALSE;
2266         }
2267
2268         _dbus_verbose("Policy %s set correctly\n", name);
2269         return TRUE;
2270 }
2271
2272 dbus_bool_t bus_register_kdbus(char* name, DBusConnection *connection, DBusError *error)
2273 {
2274         struct kdbus_cmd_hello hello;
2275         int fd;
2276
2277         memset(&hello, 0, sizeof(hello));
2278         hello.conn_flags = KDBUS_HELLO_ACCEPT_FD |
2279                            KDBUS_HELLO_ATTACH_COMM |
2280                            KDBUS_HELLO_ATTACH_EXE |
2281                            KDBUS_HELLO_ATTACH_CMDLINE |
2282                            KDBUS_HELLO_ATTACH_CAPS |
2283                            KDBUS_HELLO_ATTACH_CGROUP |
2284                            KDBUS_HELLO_ATTACH_SECLABEL |
2285                            KDBUS_HELLO_ATTACH_AUDIT;
2286         hello.size = sizeof(struct kdbus_cmd_hello);
2287         hello.pool_size = POOL_SIZE;
2288
2289         if(!dbus_connection_get_socket(connection, &fd))
2290         {
2291                 dbus_set_error (error, "failed to get fd for bus registration", NULL);
2292                 return FALSE;
2293         }
2294         if (ioctl(fd, KDBUS_CMD_HELLO, &hello))
2295         {
2296                 dbus_set_error(error,_dbus_error_from_errno (errno), "Failed to send hello: %s", _dbus_strerror (errno));
2297                 return FALSE;
2298         }
2299
2300         _dbus_verbose("-- Our peer ID is: %llu\n", (unsigned long long)hello.id);
2301         sprintf(name, "%llu", (unsigned long long)hello.id);
2302
2303         if(!kdbus_mmap(dbus_connection_get_transport(connection)))
2304         {
2305                 dbus_set_error(error,_dbus_error_from_errno (errno), "Error when mmap: %s", _dbus_strerror (errno));
2306                 return FALSE;
2307         }
2308
2309         return TRUE;
2310 }
2311
2312 uint64_t bus_request_name_kdbus(DBusConnection *connection, const char *name, const uint64_t flags, DBusError *error)
2313 {
2314         struct kdbus_cmd_name *cmd_name;
2315         int fd;
2316         uint64_t size = sizeof(*cmd_name) + strlen(name) + 1;
2317         uint64_t flags_kdbus = 0;
2318
2319         cmd_name = alloca(size);
2320
2321         memset(cmd_name, 0, size);
2322         strcpy(cmd_name->name, name);
2323         cmd_name->size = size;
2324
2325         if(flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT)
2326                 flags_kdbus |= KDBUS_NAME_ALLOW_REPLACEMENT;
2327         if(!(flags & DBUS_NAME_FLAG_DO_NOT_QUEUE))
2328                 flags_kdbus |= KDBUS_NAME_QUEUE;
2329         if(flags & DBUS_NAME_FLAG_REPLACE_EXISTING)
2330                 flags_kdbus |= KDBUS_NAME_REPLACE_EXISTING;
2331
2332         cmd_name->conn_flags = flags_kdbus;
2333
2334         if(!dbus_connection_get_socket(connection, &fd))
2335         {
2336                 dbus_set_error (error, "failed to get fd for name request", NULL);
2337                 return FALSE;
2338         }
2339
2340         _dbus_verbose("Request name - flags sent: 0x%llx       !!!!!!!!!\n", cmd_name->conn_flags);
2341
2342         _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2343         if (ioctl(fd, KDBUS_CMD_NAME_ACQUIRE, cmd_name))
2344         {
2345                 dbus_set_error(error,_dbus_error_from_errno (errno), "error acquiring name: %s", _dbus_strerror (errno));
2346                 if(errno == EEXIST)
2347                         return DBUS_REQUEST_NAME_REPLY_EXISTS;
2348                 return FALSE;
2349         }
2350
2351         _dbus_verbose("Request name - received flag: 0x%llx       !!!!!!!!!\n", cmd_name->conn_flags);
2352
2353         if(cmd_name->conn_flags & KDBUS_NAME_IN_QUEUE)
2354                 return DBUS_REQUEST_NAME_REPLY_IN_QUEUE;
2355         else
2356                 return DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
2357         //todo now 1 codes are never returned -  DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER
2358 }
2359
2360 /**
2361  * Checks if the connection's transport is kdbus on the basis of its address
2362  *
2363  * @param pointer to the connection
2364  * @returns TRUE if kdbus transport, otherwise FALSE
2365  */
2366 dbus_bool_t dbus_transport_is_kdbus(DBusConnection *connection)
2367 {
2368         const char* address = _dbus_connection_get_address(connection);
2369
2370         if(address == strstr(address, "kdbus:path="))
2371                 return TRUE;
2372         else
2373                 return FALSE;
2374 }
2375
2376 void dbus_bus_add_match_kdbus (DBusConnection *connection, const char *rule, DBusError *error)
2377 {
2378         struct kdbus_cmd_match cmd_match;
2379         int fd;
2380
2381         memset(&cmd_match, 0, sizeof(cmd_match));
2382
2383         if(!dbus_connection_get_socket(connection, &fd))
2384         {
2385                 dbus_set_error (error, "failed to get fd for add match", NULL);
2386                 return;
2387         }
2388
2389         cmd_match.size = sizeof(cmd_match);
2390
2391         //todo add matching rules from *rule when it will be docuemnted in kdbus
2392
2393
2394         cmd_match.src_id = KDBUS_MATCH_SRC_ID_ANY;
2395
2396         if (ioctl(fd, KDBUS_CMD_MATCH_ADD, &cmd_match))
2397                 dbus_set_error(error,_dbus_error_from_errno (errno), "error adding match: %s", _dbus_strerror (errno));
2398
2399         _dbus_verbose("Finished adding match bus rule %s             !!!!!!!!!\n", rule);
2400 }