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