Add .dbus-keyrings
[platform/upstream/dbus.git] / dbus / dbus-transport-unix.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-transport-unix.c UNIX socket subclasses of DBusTransport
3  *
4  * Copyright (C) 2002, 2003  Red Hat Inc.
5  *
6  * Licensed under the Academic Free License version 1.2
7  * 
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  * 
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23
24 #include "dbus-internals.h"
25 #include "dbus-connection-internal.h"
26 #include "dbus-transport-unix.h"
27 #include "dbus-transport-protected.h"
28 #include "dbus-watch.h"
29 #include <sys/types.h>
30 #include <sys/time.h>
31 #include <unistd.h>
32
33
34 /**
35  * @defgroup DBusTransportUnix DBusTransport implementations for UNIX
36  * @ingroup  DBusInternals
37  * @brief Implementation details of DBusTransport on UNIX
38  *
39  * @{
40  */
41
42 /**
43  * Opaque object representing a Unix file descriptor transport.
44  */
45 typedef struct DBusTransportUnix DBusTransportUnix;
46
47 /**
48  * Implementation details of DBusTransportUnix. All members are private.
49  */
50 struct DBusTransportUnix
51 {
52   DBusTransport base;                   /**< Parent instance */
53   int fd;                               /**< File descriptor. */
54   DBusWatch *read_watch;                /**< Watch for readability. */
55   DBusWatch *write_watch;               /**< Watch for writability. */
56
57   int max_bytes_read_per_iteration;     /**< To avoid blocking too long. */
58   int max_bytes_written_per_iteration;  /**< To avoid blocking too long. */
59
60   int message_bytes_written;            /**< Number of bytes of current
61                                          *   outgoing message that have
62                                          *   been written.
63                                          */
64   DBusString encoded_outgoing;          /**< Encoded version of current
65                                          *   outgoing message.
66                                          */
67   DBusString encoded_incoming;          /**< Encoded version of current
68                                          *   incoming data.
69                                          */
70 };
71
72 static void
73 free_watches (DBusTransport *transport)
74 {
75   DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
76   
77   if (unix_transport->read_watch)
78     {
79       if (transport->connection)
80         _dbus_connection_remove_watch (transport->connection,
81                                        unix_transport->read_watch);
82       _dbus_watch_invalidate (unix_transport->read_watch);
83       _dbus_watch_unref (unix_transport->read_watch);
84       unix_transport->read_watch = NULL;
85     }
86
87   if (unix_transport->write_watch)
88     {
89       if (transport->connection)
90         _dbus_connection_remove_watch (transport->connection,
91                                        unix_transport->write_watch);
92       _dbus_watch_invalidate (unix_transport->write_watch);
93       _dbus_watch_unref (unix_transport->write_watch);
94       unix_transport->write_watch = NULL;
95     }
96 }
97
98 static void
99 unix_finalize (DBusTransport *transport)
100 {
101   DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
102   
103   free_watches (transport);
104
105   _dbus_string_free (&unix_transport->encoded_outgoing);
106   _dbus_string_free (&unix_transport->encoded_incoming);
107   
108   _dbus_transport_finalize_base (transport);
109
110   _dbus_assert (unix_transport->read_watch == NULL);
111   _dbus_assert (unix_transport->write_watch == NULL);
112   
113   dbus_free (transport);
114 }
115
116 static void
117 check_write_watch (DBusTransport *transport)
118 {
119   DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
120   dbus_bool_t need_write_watch;
121
122   if (transport->connection == NULL)
123     return;
124
125   if (transport->disconnected)
126     {
127       _dbus_assert (unix_transport->write_watch == NULL);
128       return;
129     }
130   
131   _dbus_transport_ref (transport);
132
133   if (_dbus_transport_get_is_authenticated (transport))
134     need_write_watch = transport->messages_need_sending;
135   else
136     need_write_watch = transport->send_credentials_pending ||
137       _dbus_auth_do_work (transport->auth) == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND;
138
139   _dbus_connection_toggle_watch (transport->connection,
140                                  unix_transport->write_watch,
141                                  need_write_watch);
142
143   _dbus_transport_unref (transport);
144 }
145
146 static void
147 check_read_watch (DBusTransport *transport)
148 {
149   DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
150   dbus_bool_t need_read_watch;
151
152   if (transport->connection == NULL)
153     return;
154
155   if (transport->disconnected)
156     {
157       _dbus_assert (unix_transport->read_watch == NULL);
158       return;
159     }
160   
161   _dbus_transport_ref (transport);
162
163   if (_dbus_transport_get_is_authenticated (transport))
164     need_read_watch =
165       _dbus_counter_get_value (transport->live_messages_size) < transport->max_live_messages_size;
166   else
167     need_read_watch = transport->receive_credentials_pending ||
168       _dbus_auth_do_work (transport->auth) == DBUS_AUTH_STATE_WAITING_FOR_INPUT;
169
170   _dbus_connection_toggle_watch (transport->connection,
171                                  unix_transport->read_watch,
172                                  need_read_watch);
173
174   _dbus_transport_unref (transport);
175 }
176
177 static void
178 do_io_error (DBusTransport *transport)
179 {
180   _dbus_transport_ref (transport);
181   _dbus_transport_disconnect (transport);
182   _dbus_transport_unref (transport);
183 }
184
185 /* return value is whether we successfully read any new data. */
186 static dbus_bool_t
187 read_data_into_auth (DBusTransport *transport,
188                      dbus_bool_t   *oom)
189 {
190   DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
191   DBusString *buffer;
192   int bytes_read;
193   
194   *oom = FALSE;
195
196   _dbus_auth_get_buffer (transport->auth, &buffer);
197   
198   bytes_read = _dbus_read (unix_transport->fd,
199                            buffer, unix_transport->max_bytes_read_per_iteration);
200
201   _dbus_auth_return_buffer (transport->auth, buffer,
202                             bytes_read > 0 ? bytes_read : 0);
203
204   if (bytes_read > 0)
205     {
206       _dbus_verbose (" read %d bytes in auth phase\n", bytes_read);
207
208       return TRUE;
209     }
210   else if (bytes_read < 0)
211     {
212       /* EINTR already handled for us */
213
214       if (errno == ENOMEM)
215         {
216           *oom = TRUE;
217         }
218       else if (errno == EAGAIN ||
219                errno == EWOULDBLOCK)
220         ; /* do nothing, just return FALSE below */
221       else
222         {
223           _dbus_verbose ("Error reading from remote app: %s\n",
224                          _dbus_strerror (errno));
225           do_io_error (transport);
226         }
227
228       return FALSE;
229     }
230   else
231     {
232       _dbus_assert (bytes_read == 0);
233       
234       _dbus_verbose ("Disconnected from remote app\n");
235       do_io_error (transport);
236
237       return FALSE;
238     }
239 }
240
241 /* Return value is whether we successfully wrote any bytes */
242 static dbus_bool_t
243 write_data_from_auth (DBusTransport *transport)
244 {
245   DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
246   int bytes_written;
247   const DBusString *buffer;
248
249   if (!_dbus_auth_get_bytes_to_send (transport->auth,
250                                      &buffer))
251     return FALSE;
252   
253   bytes_written = _dbus_write (unix_transport->fd,
254                                buffer,
255                                0, _dbus_string_get_length (buffer));
256
257   if (bytes_written > 0)
258     {
259       _dbus_auth_bytes_sent (transport->auth, bytes_written);
260       return TRUE;
261     }
262   else if (bytes_written < 0)
263     {
264       /* EINTR already handled for us */
265       
266       if (errno == EAGAIN ||
267           errno == EWOULDBLOCK)
268         ;
269       else
270         {
271           _dbus_verbose ("Error writing to remote app: %s\n",
272                          _dbus_strerror (errno));
273           do_io_error (transport);
274         }
275     }
276
277   return FALSE;
278 }
279
280 static void
281 exchange_credentials (DBusTransport *transport,
282                       dbus_bool_t    do_reading,
283                       dbus_bool_t    do_writing)
284 {
285   DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
286
287   if (do_writing && transport->send_credentials_pending)
288     {
289       if (_dbus_send_credentials_unix_socket (unix_transport->fd,
290                                               NULL))
291         {
292           transport->send_credentials_pending = FALSE;
293         }
294       else
295         {
296           _dbus_verbose ("Failed to write credentials\n");
297           do_io_error (transport);
298         }
299     }
300   
301   if (do_reading && transport->receive_credentials_pending)
302     {
303       if (_dbus_read_credentials_unix_socket (unix_transport->fd,
304                                                &transport->credentials,
305                                                NULL))
306         {
307           transport->receive_credentials_pending = FALSE;
308         }
309       else
310         {
311           _dbus_verbose ("Failed to read credentials\n");
312           do_io_error (transport);
313         }
314     }
315
316   if (!(transport->send_credentials_pending ||
317         transport->receive_credentials_pending))
318     {
319       _dbus_auth_set_credentials (transport->auth,
320                                   &transport->credentials);
321     }
322 }
323
324 static dbus_bool_t
325 do_authentication (DBusTransport *transport,
326                    dbus_bool_t    do_reading,
327                    dbus_bool_t    do_writing)
328 {
329   dbus_bool_t oom;
330   
331   _dbus_transport_ref (transport);
332
333   oom = FALSE;
334   
335   while (!_dbus_transport_get_is_authenticated (transport) &&
336          _dbus_transport_get_is_connected (transport))
337     {      
338       exchange_credentials (transport, do_reading, do_writing);
339       
340       if (transport->send_credentials_pending ||
341           transport->receive_credentials_pending)
342         {
343           _dbus_verbose ("send_credentials_pending = %d receive_credentials_pending = %d\n",
344                          transport->send_credentials_pending,
345                          transport->receive_credentials_pending);
346           goto out;
347         }
348
349 #define TRANSPORT_SIDE(t) ((t)->is_server ? "server" : "client")
350       switch (_dbus_auth_do_work (transport->auth))
351         {
352         case DBUS_AUTH_STATE_WAITING_FOR_INPUT:
353           _dbus_verbose (" %s auth state: waiting for input\n",
354                          TRANSPORT_SIDE (transport));
355           if (!do_reading || !read_data_into_auth (transport, &oom))
356             goto out;
357           break;
358       
359         case DBUS_AUTH_STATE_WAITING_FOR_MEMORY:
360           _dbus_verbose (" %s auth state: waiting for memory\n",
361                          TRANSPORT_SIDE (transport));
362           oom = TRUE;
363           goto out;
364           break;
365       
366         case DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND:
367           _dbus_verbose (" %s auth state: bytes to send\n",
368                          TRANSPORT_SIDE (transport));
369           if (!do_writing || !write_data_from_auth (transport))
370             goto out;
371           break;
372       
373         case DBUS_AUTH_STATE_NEED_DISCONNECT:
374           _dbus_verbose (" %s auth state: need to disconnect\n",
375                          TRANSPORT_SIDE (transport));
376           do_io_error (transport);
377           break;
378       
379         case DBUS_AUTH_STATE_AUTHENTICATED_WITH_UNUSED_BYTES:
380           _dbus_verbose (" %s auth state: auth with unused bytes\n",
381                          TRANSPORT_SIDE (transport));
382           /* We'll recover the unused bytes in dbus-transport.c */
383           goto out;
384           break;
385           
386         case DBUS_AUTH_STATE_AUTHENTICATED:
387           _dbus_verbose (" %s auth state: authenticated\n",
388                          TRANSPORT_SIDE (transport));
389           break;
390         }
391     }
392   
393  out:
394   check_read_watch (transport);
395   check_write_watch (transport);
396   _dbus_transport_unref (transport);
397
398   if (oom)
399     return FALSE;
400   else
401     return TRUE;
402 }
403
404 /* returns false on oom */
405 static dbus_bool_t
406 do_writing (DBusTransport *transport)
407 {
408   int total;
409   DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
410   dbus_bool_t oom;
411   
412   /* No messages without authentication! */
413   if (!_dbus_transport_get_is_authenticated (transport))
414     {
415       _dbus_verbose ("Not authenticated, not writing anything\n");
416       return TRUE;
417     }
418
419   if (transport->disconnected)
420     {
421       _dbus_verbose ("Not connected, not writing anything\n");
422       return TRUE;
423     }
424
425 #if 0
426   _dbus_verbose ("do_writing(), have_messages = %d\n",
427                  _dbus_connection_have_messages_to_send (transport->connection));
428 #endif
429   
430   oom = FALSE;
431   total = 0;
432
433   while (!transport->disconnected &&
434          _dbus_connection_have_messages_to_send (transport->connection))
435     {
436       int bytes_written;
437       DBusMessage *message;
438       const DBusString *header;
439       const DBusString *body;
440       int header_len, body_len;
441       int total_bytes_to_write;
442       
443       if (total > unix_transport->max_bytes_written_per_iteration)
444         {
445           _dbus_verbose ("%d bytes exceeds %d bytes written per iteration, returning\n",
446                          total, unix_transport->max_bytes_written_per_iteration);
447           goto out;
448         }
449
450       if (!dbus_watch_get_enabled (unix_transport->write_watch))
451         {
452           _dbus_verbose ("write watch disabled, not writing more stuff\n");
453           goto out;
454         }
455       
456       message = _dbus_connection_get_message_to_send (transport->connection);
457       _dbus_assert (message != NULL);
458       _dbus_message_lock (message);
459
460 #if 0
461       _dbus_verbose ("writing message %p\n", message);
462 #endif
463       
464       _dbus_message_get_network_data (message,
465                                       &header, &body);
466
467       header_len = _dbus_string_get_length (header);
468       body_len = _dbus_string_get_length (body);
469
470       if (_dbus_auth_needs_encoding (transport->auth))
471         {
472           if (_dbus_string_get_length (&unix_transport->encoded_outgoing) == 0)
473             {
474               if (!_dbus_auth_encode_data (transport->auth,
475                                            header, &unix_transport->encoded_outgoing))
476                 {
477                   oom = TRUE;
478                   goto out;
479                 }
480               
481               if (!_dbus_auth_encode_data (transport->auth,
482                                            body, &unix_transport->encoded_outgoing))
483                 {
484                   _dbus_string_set_length (&unix_transport->encoded_outgoing, 0);
485                   oom = TRUE;
486                   goto out;
487                 }
488             }
489           
490           total_bytes_to_write = _dbus_string_get_length (&unix_transport->encoded_outgoing);
491
492 #if 0
493           _dbus_verbose ("encoded message is %d bytes\n",
494                          total_bytes_to_write);
495 #endif
496           
497           bytes_written =
498             _dbus_write (unix_transport->fd,
499                          &unix_transport->encoded_outgoing,
500                          unix_transport->message_bytes_written,
501                          total_bytes_to_write - unix_transport->message_bytes_written);
502         }
503       else
504         {
505           total_bytes_to_write = header_len + body_len;
506
507 #if 0
508           _dbus_verbose ("message is %d bytes\n",
509                          total_bytes_to_write);          
510 #endif
511           
512           if (unix_transport->message_bytes_written < header_len)
513             {
514               bytes_written =
515                 _dbus_write_two (unix_transport->fd,
516                                  header,
517                                  unix_transport->message_bytes_written,
518                                  header_len - unix_transport->message_bytes_written,
519                                  body,
520                                  0, body_len);
521             }
522           else
523             {
524               bytes_written =
525                 _dbus_write (unix_transport->fd,
526                              body,
527                              (unix_transport->message_bytes_written - header_len),
528                              body_len -
529                              (unix_transport->message_bytes_written - header_len));
530             }
531         }
532
533       if (bytes_written < 0)
534         {
535           /* EINTR already handled for us */
536           
537           if (errno == EAGAIN ||
538               errno == EWOULDBLOCK)
539             goto out;
540           else
541             {
542               _dbus_verbose ("Error writing to remote app: %s\n",
543                              _dbus_strerror (errno));
544               do_io_error (transport);
545               goto out;
546             }
547         }
548       else
549         {
550           _dbus_verbose (" wrote %d bytes of %d\n", bytes_written,
551                          total_bytes_to_write);
552           
553           total += bytes_written;
554           unix_transport->message_bytes_written += bytes_written;
555
556           _dbus_assert (unix_transport->message_bytes_written <=
557                         total_bytes_to_write);
558           
559           if (unix_transport->message_bytes_written == total_bytes_to_write)
560             {
561               unix_transport->message_bytes_written = 0;
562               _dbus_string_set_length (&unix_transport->encoded_outgoing, 0);
563
564               _dbus_connection_message_sent (transport->connection,
565                                              message);
566             }
567         }
568     }
569
570  out:
571   if (oom)
572     return FALSE;
573   else
574     return TRUE;
575 }
576
577 /* returns false on out-of-memory */
578 static dbus_bool_t
579 do_reading (DBusTransport *transport)
580 {
581   DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
582   DBusString *buffer;
583   int bytes_read;
584   int total;
585   dbus_bool_t oom;
586
587   /* No messages without authentication! */
588   if (!_dbus_transport_get_is_authenticated (transport))
589     return TRUE;
590
591   oom = FALSE;
592   
593   total = 0;
594
595  again:
596   
597   /* See if we've exceeded max messages and need to disable reading */
598   check_read_watch (transport);
599   
600   if (total > unix_transport->max_bytes_read_per_iteration)
601     {
602       _dbus_verbose ("%d bytes exceeds %d bytes read per iteration, returning\n",
603                      total, unix_transport->max_bytes_read_per_iteration);
604       goto out;
605     }
606
607   _dbus_assert (unix_transport->read_watch != NULL ||
608                 transport->disconnected);
609   
610   if (transport->disconnected)
611     goto out;
612
613   if (!dbus_watch_get_enabled (unix_transport->read_watch))
614     return TRUE;
615   
616   if (_dbus_auth_needs_decoding (transport->auth))
617     {
618       if (_dbus_string_get_length (&unix_transport->encoded_incoming) > 0)
619         bytes_read = _dbus_string_get_length (&unix_transport->encoded_incoming);
620       else
621         bytes_read = _dbus_read (unix_transport->fd,
622                                  &unix_transport->encoded_incoming,
623                                  unix_transport->max_bytes_read_per_iteration);
624
625       _dbus_assert (_dbus_string_get_length (&unix_transport->encoded_incoming) ==
626                     bytes_read);
627       
628       if (bytes_read > 0)
629         {
630           int orig_len;
631           
632           _dbus_message_loader_get_buffer (transport->loader,
633                                            &buffer);
634
635           orig_len = _dbus_string_get_length (buffer);
636           
637           if (!_dbus_auth_decode_data (transport->auth,
638                                        &unix_transport->encoded_incoming,
639                                        buffer))
640             {
641               _dbus_verbose ("Out of memory decoding incoming data\n");
642               oom = TRUE;
643               goto out;
644             }
645
646           _dbus_message_loader_return_buffer (transport->loader,
647                                               buffer,
648                                               _dbus_string_get_length (buffer) - orig_len);
649
650           _dbus_string_set_length (&unix_transport->encoded_incoming, 0);
651         }
652     }
653   else
654     {
655       _dbus_message_loader_get_buffer (transport->loader,
656                                        &buffer);
657       
658       bytes_read = _dbus_read (unix_transport->fd,
659                                buffer, unix_transport->max_bytes_read_per_iteration);
660       
661       _dbus_message_loader_return_buffer (transport->loader,
662                                           buffer,
663                                           bytes_read < 0 ? 0 : bytes_read);
664     }
665   
666   if (bytes_read < 0)
667     {
668       /* EINTR already handled for us */
669
670       if (errno == ENOMEM)
671         {
672           _dbus_verbose ("Out of memory in read()/do_reading()\n");
673           oom = TRUE;
674           goto out;
675         }
676       else if (errno == EAGAIN ||
677                errno == EWOULDBLOCK)
678         goto out;
679       else
680         {
681           _dbus_verbose ("Error reading from remote app: %s\n",
682                          _dbus_strerror (errno));
683           do_io_error (transport);
684           goto out;
685         }
686     }
687   else if (bytes_read == 0)
688     {
689       _dbus_verbose ("Disconnected from remote app\n");
690       do_io_error (transport);
691       goto out;
692     }
693   else
694     {
695       _dbus_verbose (" read %d bytes\n", bytes_read);
696       
697       total += bytes_read;      
698
699       if (_dbus_transport_queue_messages (transport) == DBUS_DISPATCH_NEED_MEMORY)
700         {
701           oom = TRUE;
702           _dbus_verbose (" out of memory when queueing messages we just read in the transport\n");
703           goto out;
704         }
705       
706       /* Try reading more data until we get EAGAIN and return, or
707        * exceed max bytes per iteration.  If in blocking mode of
708        * course we'll block instead of returning.
709        */
710       goto again;
711     }
712
713  out:
714   if (oom)
715     return FALSE;
716   else
717     return TRUE;
718 }
719
720 static dbus_bool_t
721 unix_handle_watch (DBusTransport *transport,
722                    DBusWatch     *watch,
723                    unsigned int   flags)
724 {
725   DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
726
727   _dbus_assert (watch == unix_transport->read_watch ||
728                 watch == unix_transport->write_watch);
729   
730   if (flags & (DBUS_WATCH_HANGUP | DBUS_WATCH_ERROR))
731     {
732       _dbus_transport_disconnect (transport);
733       return TRUE;
734     }
735   
736   if (watch == unix_transport->read_watch &&
737       (flags & DBUS_WATCH_READABLE))
738     {
739 #if 1
740       _dbus_verbose ("handling read watch\n");
741 #endif
742       if (!do_authentication (transport, TRUE, FALSE))
743         return FALSE;
744       
745       if (!do_reading (transport))
746         {
747           _dbus_verbose ("no memory to read\n");
748           return FALSE;
749         }
750     }
751   else if (watch == unix_transport->write_watch &&
752            (flags & DBUS_WATCH_WRITABLE))
753     {
754 #if 0
755       _dbus_verbose ("handling write watch, messages_need_sending = %d\n",
756                      transport->messages_need_sending);
757 #endif
758       if (!do_authentication (transport, FALSE, TRUE))
759         return FALSE;
760       
761       if (!do_writing (transport))
762         {
763           _dbus_verbose ("no memory to write\n");
764           return FALSE;
765         }
766     }
767 #ifdef DBUS_ENABLE_VERBOSE_MODE
768   else
769     {
770       if (watch == unix_transport->read_watch)
771         _dbus_verbose ("asked to handle read watch with non-read condition 0x%x\n",
772                        flags);
773       else if (watch == unix_transport->write_watch)
774         _dbus_verbose ("asked to handle write watch with non-write condition 0x%x\n",
775                        flags);
776       else
777         _dbus_verbose ("asked to handle watch %p on fd %d that we don't recognize\n",
778                        watch, dbus_watch_get_fd (watch));
779     }
780 #endif /* DBUS_ENABLE_VERBOSE_MODE */
781
782   return TRUE;
783 }
784
785 static void
786 unix_disconnect (DBusTransport *transport)
787 {
788   DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
789   
790   free_watches (transport);
791   
792   _dbus_close (unix_transport->fd, NULL);
793   unix_transport->fd = -1;
794 }
795
796 static dbus_bool_t
797 unix_connection_set (DBusTransport *transport)
798 {
799   DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
800
801   _dbus_watch_set_handler (unix_transport->write_watch,
802                            _dbus_connection_handle_watch,
803                            transport->connection, NULL);
804
805   _dbus_watch_set_handler (unix_transport->read_watch,
806                            _dbus_connection_handle_watch,
807                            transport->connection, NULL);
808   
809   if (!_dbus_connection_add_watch (transport->connection,
810                                    unix_transport->write_watch))
811     return FALSE;
812
813   if (!_dbus_connection_add_watch (transport->connection,
814                                    unix_transport->read_watch))
815     {
816       _dbus_connection_remove_watch (transport->connection,
817                                      unix_transport->write_watch);
818       return FALSE;
819     }
820
821   check_read_watch (transport);
822   check_write_watch (transport);
823
824   return TRUE;
825 }
826
827 static void
828 unix_messages_pending (DBusTransport *transport,
829                        int            messages_pending)
830 {
831   check_write_watch (transport);
832 }
833
834 /* FIXME use _dbus_poll(), not select() */
835 /**
836  * @todo We need to have a way to wake up the select sleep if
837  * a new iteration request comes in with a flag (read/write) that
838  * we're not currently serving. Otherwise a call that just reads
839  * could block a write call forever (if there are no incoming
840  * messages).
841  */
842 static  void
843 unix_do_iteration (DBusTransport *transport,
844                    unsigned int   flags,
845                    int            timeout_milliseconds)
846 {
847   DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
848   fd_set read_set;
849   fd_set write_set;
850   dbus_bool_t do_select;
851   int select_res;
852
853   _dbus_verbose (" iteration flags = %s%s timeout = %d read_watch = %p write_watch = %p\n",
854                  flags & DBUS_ITERATION_DO_READING ? "read" : "",
855                  flags & DBUS_ITERATION_DO_WRITING ? "write" : "",
856                  timeout_milliseconds,
857                  unix_transport->read_watch,
858                  unix_transport->write_watch);
859   
860   /* "again" has to be up here because on EINTR the fd sets become
861    * undefined
862    */
863  again:
864   
865   do_select = FALSE;
866
867   /* the passed in DO_READING/DO_WRITING flags indicate whether to
868    * read/write messages, but regardless of those we may need to block
869    * for reading/writing to do auth.  But if we do reading for auth,
870    * we don't want to read any messages yet if not given DO_READING.
871    *
872    * Also, if read_watch == NULL or write_watch == NULL, we don't
873    * want to read/write so don't.
874    */
875
876   FD_ZERO (&read_set);
877   FD_ZERO (&write_set);
878   
879   if (_dbus_transport_get_is_authenticated (transport))
880     {
881       if (unix_transport->read_watch &&
882           (flags & DBUS_ITERATION_DO_READING))
883         {
884           FD_SET (unix_transport->fd, &read_set);
885           do_select = TRUE;
886         }
887       
888       if (unix_transport->write_watch &&
889           (flags & DBUS_ITERATION_DO_WRITING))
890         {
891           FD_SET (unix_transport->fd, &write_set);
892           do_select = TRUE;
893         }
894     }
895   else
896     {
897       DBusAuthState auth_state;
898       
899       auth_state = _dbus_auth_do_work (transport->auth);
900
901       if (transport->receive_credentials_pending ||
902           auth_state == DBUS_AUTH_STATE_WAITING_FOR_INPUT)
903         {
904           FD_SET (unix_transport->fd, &read_set);
905           do_select = TRUE;
906         }
907
908       if (transport->send_credentials_pending ||
909           auth_state == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND)
910         {
911           FD_SET (unix_transport->fd, &write_set);
912           do_select = TRUE;
913         }
914     } 
915
916   if (do_select)
917     {
918       fd_set err_set;
919       struct timeval timeout;
920       dbus_bool_t use_timeout;
921       
922       FD_ZERO (&err_set);
923       FD_SET (unix_transport->fd, &err_set);
924   
925       if (flags & DBUS_ITERATION_BLOCK)
926         {
927           if (timeout_milliseconds >= 0)
928             {
929               timeout.tv_sec = timeout_milliseconds / 1000;
930               timeout.tv_usec = (timeout_milliseconds % 1000) * 1000;
931               
932               /* Always use timeout if one is passed in. */
933               use_timeout = TRUE;
934             }
935           else
936             {
937               use_timeout = FALSE; /* NULL timeout to block forever */
938             }
939         }
940       else
941         {
942           /* 0 timeout to not block */
943           timeout.tv_sec = 0;
944           timeout.tv_usec = 0;
945           use_timeout = TRUE;
946         }
947
948       /* For blocking selects we drop the connection lock here
949        * to avoid blocking out connection access during a potentially
950        * indefinite blocking call. The io path is still protected
951        * by the io_path_cond condvar, so we won't reenter this.
952        */
953       if (flags & DBUS_ITERATION_BLOCK)
954         _dbus_connection_unlock (transport->connection);
955       
956       select_res = select (unix_transport->fd + 1,
957                            &read_set, &write_set, &err_set,
958                            use_timeout ? &timeout : NULL);
959
960       if (flags & DBUS_ITERATION_BLOCK)
961         _dbus_connection_lock (transport->connection);
962       
963       
964       if (select_res >= 0)
965         {
966           if (FD_ISSET (unix_transport->fd, &err_set))
967             do_io_error (transport);
968           else
969             {
970               dbus_bool_t need_read = FD_ISSET (unix_transport->fd, &read_set);
971               dbus_bool_t need_write = FD_ISSET (unix_transport->fd, &write_set);
972
973               _dbus_verbose ("in iteration, need_read=%d need_write=%d\n",
974                              need_read, need_write);
975               do_authentication (transport, need_read, need_write);
976                                  
977               if (need_read && (flags & DBUS_ITERATION_DO_READING))
978                 do_reading (transport);
979               if (need_write && (flags & DBUS_ITERATION_DO_WRITING))
980                 do_writing (transport);
981             }
982         }
983       else if (errno == EINTR)
984         goto again;
985       else
986         {
987           _dbus_verbose ("Error from select(): %s\n",
988                          _dbus_strerror (errno));
989         }
990     }
991 }
992
993 static void
994 unix_live_messages_changed (DBusTransport *transport)
995 {
996   /* See if we should look for incoming messages again */
997   check_read_watch (transport);
998 }
999
1000 static DBusTransportVTable unix_vtable = {
1001   unix_finalize,
1002   unix_handle_watch,
1003   unix_disconnect,
1004   unix_connection_set,
1005   unix_messages_pending,
1006   unix_do_iteration,
1007   unix_live_messages_changed
1008 };
1009
1010 /**
1011  * Creates a new transport for the given file descriptor.  The file
1012  * descriptor must be nonblocking (use _dbus_set_fd_nonblocking() to
1013  * make it so). This function is shared by various transports that
1014  * boil down to a full duplex file descriptor.
1015  *
1016  * @param fd the file descriptor.
1017  * @param server #TRUE if this transport is on the server side of a connection
1018  * @param address the transport's address
1019  * @returns the new transport, or #NULL if no memory.
1020  */
1021 DBusTransport*
1022 _dbus_transport_new_for_fd (int               fd,
1023                             dbus_bool_t       server,
1024                             const DBusString *address)
1025 {
1026   DBusTransportUnix *unix_transport;
1027   
1028   unix_transport = dbus_new0 (DBusTransportUnix, 1);
1029   if (unix_transport == NULL)
1030     return NULL;
1031
1032   if (!_dbus_string_init (&unix_transport->encoded_outgoing))
1033     goto failed_0;
1034
1035   if (!_dbus_string_init (&unix_transport->encoded_incoming))
1036     goto failed_1;
1037   
1038   unix_transport->write_watch = _dbus_watch_new (fd,
1039                                                  DBUS_WATCH_WRITABLE,
1040                                                  FALSE,
1041                                                  NULL, NULL, NULL);
1042   if (unix_transport->write_watch == NULL)
1043     goto failed_2;
1044   
1045   unix_transport->read_watch = _dbus_watch_new (fd,
1046                                                 DBUS_WATCH_READABLE,
1047                                                 FALSE,
1048                                                 NULL, NULL, NULL);
1049   if (unix_transport->read_watch == NULL)
1050     goto failed_3;
1051   
1052   if (!_dbus_transport_init_base (&unix_transport->base,
1053                                   &unix_vtable,
1054                                   server, address))
1055     goto failed_4;
1056   
1057   unix_transport->fd = fd;
1058   unix_transport->message_bytes_written = 0;
1059   
1060   /* These values should probably be tunable or something. */     
1061   unix_transport->max_bytes_read_per_iteration = 2048;
1062   unix_transport->max_bytes_written_per_iteration = 2048;
1063   
1064   return (DBusTransport*) unix_transport;
1065
1066  failed_4:
1067   _dbus_watch_unref (unix_transport->read_watch);
1068  failed_3:
1069   _dbus_watch_unref (unix_transport->write_watch);
1070  failed_2:
1071   _dbus_string_free (&unix_transport->encoded_incoming);
1072  failed_1:
1073   _dbus_string_free (&unix_transport->encoded_outgoing);
1074  failed_0:
1075   dbus_free (unix_transport);
1076   return NULL;
1077 }
1078
1079 /**
1080  * Creates a new transport for the given Unix domain socket
1081  * path. This creates a client-side of a transport.
1082  *
1083  * @todo once we add a way to escape paths in a dbus
1084  * address, this function needs to do escaping.
1085  *
1086  * @param path the path to the domain socket.
1087  * @param abstract #TRUE to use abstract socket namespace
1088  * @param error address where an error can be returned.
1089  * @returns a new transport, or #NULL on failure.
1090  */
1091 DBusTransport*
1092 _dbus_transport_new_for_domain_socket (const char     *path,
1093                                        dbus_bool_t     abstract,
1094                                        DBusError      *error)
1095 {
1096   int fd;
1097   DBusTransport *transport;
1098   DBusString address;
1099   
1100   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1101
1102   if (!_dbus_string_init (&address))
1103     {
1104       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1105       return NULL;
1106     }
1107
1108   fd = -1;
1109
1110   if ((abstract &&
1111        !_dbus_string_append (&address, "unix:abstract=")) ||
1112       (!abstract &&
1113        !_dbus_string_append (&address, "unix:path=")) ||
1114       !_dbus_string_append (&address, path))
1115     {
1116       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1117       goto failed_0;
1118     }
1119   
1120   fd = _dbus_connect_unix_socket (path, abstract, error);
1121   if (fd < 0)
1122     {
1123       _DBUS_ASSERT_ERROR_IS_SET (error);
1124       goto failed_0;
1125     }
1126
1127   _dbus_fd_set_close_on_exec (fd);
1128   
1129   _dbus_verbose ("Successfully connected to unix socket %s\n",
1130                  path);
1131
1132   transport = _dbus_transport_new_for_fd (fd, FALSE, &address);
1133   if (transport == NULL)
1134     {
1135       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1136       goto failed_1;
1137     }
1138   
1139   _dbus_string_free (&address);
1140   
1141   return transport;
1142
1143  failed_1:
1144   _dbus_close (fd, NULL);
1145  failed_0:
1146   _dbus_string_free (&address);
1147   return NULL;
1148 }
1149
1150 /**
1151  * Creates a new transport for the given hostname and port.
1152  *
1153  * @param host the host to connect to
1154  * @param port the port to connect to
1155  * @param error location to store reason for failure.
1156  * @returns a new transport, or #NULL on failure.
1157  */
1158 DBusTransport*
1159 _dbus_transport_new_for_tcp_socket (const char     *host,
1160                                     dbus_int32_t    port,
1161                                     DBusError      *error)
1162 {
1163   int fd;
1164   DBusTransport *transport;
1165   DBusString address;
1166   
1167   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1168
1169   if (!_dbus_string_init (&address))
1170     {
1171       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1172       return NULL;
1173     }
1174   
1175   if (!_dbus_string_append (&address, "tcp:host=") ||
1176       !_dbus_string_append (&address, host) ||
1177       !_dbus_string_append (&address, ",port=") ||
1178       !_dbus_string_append_int (&address, port))
1179     {
1180       _dbus_string_free (&address);
1181       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1182       return NULL;
1183     }
1184   
1185   fd = _dbus_connect_tcp_socket (host, port, error);
1186   if (fd < 0)
1187     {
1188       _DBUS_ASSERT_ERROR_IS_SET (error);
1189       _dbus_string_free (&address);
1190       return NULL;
1191     }
1192
1193   _dbus_fd_set_close_on_exec (fd);
1194   
1195   _dbus_verbose ("Successfully connected to tcp socket %s:%d\n",
1196                  host, port);
1197   
1198   transport = _dbus_transport_new_for_fd (fd, FALSE, &address);
1199   if (transport == NULL)
1200     {
1201       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1202       _dbus_close (fd, NULL);
1203       _dbus_string_free (&address);
1204       fd = -1;
1205     }
1206
1207   _dbus_string_free (&address);
1208   
1209   return transport;
1210 }
1211
1212 /** @} */
1213