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