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