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