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