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