Add IgnoreOnIsolate=yes to dbus.service
[platform/upstream/dbus.git] / dbus / dbus-transport-socket.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-transport-socket.c  Socket subclasses of DBusTransport
3  *
4  * Copyright (C) 2002, 2003, 2004, 2006  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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24 #include <config.h>
25 #include "dbus-internals.h"
26 #include "dbus-connection-internal.h"
27 #include "dbus-nonce.h"
28 #include "dbus-transport-socket.h"
29 #include "dbus-transport-protected.h"
30 #include "dbus-watch.h"
31 #include "dbus-credentials.h"
32
33 /**
34  * @defgroup DBusTransportSocket DBusTransport implementations for sockets
35  * @ingroup  DBusInternals
36  * @brief Implementation details of DBusTransport on sockets
37  *
38  * @{
39  */
40
41 /**
42  * Opaque object representing a socket file descriptor transport.
43  */
44 typedef struct DBusTransportSocket DBusTransportSocket;
45
46 /**
47  * Implementation details of DBusTransportSocket. All members are private.
48  */
49 struct DBusTransportSocket
50 {
51   DBusTransport base;                   /**< Parent instance */
52   DBusSocket fd;                        /**< File descriptor. */
53   DBusWatch *read_watch;                /**< Watch for readability. */
54   DBusWatch *write_watch;               /**< Watch for writability. */
55
56   int max_bytes_read_per_iteration;     /**< To avoid blocking too long. */
57   int max_bytes_written_per_iteration;  /**< To avoid blocking too long. */
58
59   int message_bytes_written;            /**< Number of bytes of current
60                                          *   outgoing message that have
61                                          *   been written.
62                                          */
63   DBusString encoded_outgoing;          /**< Encoded version of current
64                                          *   outgoing message.
65                                          */
66   DBusString encoded_incoming;          /**< Encoded version of current
67                                          *   incoming data.
68                                          */
69 };
70
71 static void
72 free_watches (DBusTransport *transport)
73 {
74   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
75
76   _dbus_verbose ("start\n");
77   
78   if (socket_transport->read_watch)
79     {
80       if (transport->connection)
81         _dbus_connection_remove_watch_unlocked (transport->connection,
82                                                 socket_transport->read_watch);
83       _dbus_watch_invalidate (socket_transport->read_watch);
84       _dbus_watch_unref (socket_transport->read_watch);
85       socket_transport->read_watch = NULL;
86     }
87
88   if (socket_transport->write_watch)
89     {
90       if (transport->connection)
91         _dbus_connection_remove_watch_unlocked (transport->connection,
92                                                 socket_transport->write_watch);
93       _dbus_watch_invalidate (socket_transport->write_watch);
94       _dbus_watch_unref (socket_transport->write_watch);
95       socket_transport->write_watch = NULL;
96     }
97
98   _dbus_verbose ("end\n");
99 }
100
101 static void
102 socket_finalize (DBusTransport *transport)
103 {
104   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
105
106   _dbus_verbose ("\n");
107   
108   free_watches (transport);
109
110   _dbus_string_free (&socket_transport->encoded_outgoing);
111   _dbus_string_free (&socket_transport->encoded_incoming);
112   
113   _dbus_transport_finalize_base (transport);
114
115   _dbus_assert (socket_transport->read_watch == NULL);
116   _dbus_assert (socket_transport->write_watch == NULL);
117   
118   dbus_free (transport);
119 }
120
121 static void
122 check_write_watch (DBusTransport *transport)
123 {
124   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
125   dbus_bool_t needed;
126
127   if (transport->connection == NULL)
128     return;
129
130   if (transport->disconnected)
131     {
132       _dbus_assert (socket_transport->write_watch == NULL);
133       return;
134     }
135   
136   _dbus_transport_ref (transport);
137
138   if (_dbus_transport_try_to_authenticate (transport))
139     needed = _dbus_connection_has_messages_to_send_unlocked (transport->connection);
140   else
141     {
142       if (transport->send_credentials_pending)
143         needed = TRUE;
144       else
145         {
146           DBusAuthState auth_state;
147           
148           auth_state = _dbus_auth_do_work (transport->auth);
149           
150           /* If we need memory we install the write watch just in case,
151            * if there's no need for it, it will get de-installed
152            * next time we try reading.
153            */
154           if (auth_state == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND ||
155               auth_state == DBUS_AUTH_STATE_WAITING_FOR_MEMORY)
156             needed = TRUE;
157           else
158             needed = FALSE;
159         }
160     }
161
162   _dbus_verbose ("check_write_watch(): needed = %d on connection %p watch %p fd = %" DBUS_SOCKET_FORMAT " outgoing messages exist %d\n",
163                  needed, transport->connection, socket_transport->write_watch,
164                  _dbus_socket_printable (socket_transport->fd),
165                  _dbus_connection_has_messages_to_send_unlocked (transport->connection));
166
167   _dbus_connection_toggle_watch_unlocked (transport->connection,
168                                           socket_transport->write_watch,
169                                           needed);
170
171   _dbus_transport_unref (transport);
172 }
173
174 static void
175 check_read_watch (DBusTransport *transport)
176 {
177   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
178   dbus_bool_t need_read_watch;
179
180   _dbus_verbose ("fd = %" DBUS_SOCKET_FORMAT "\n",
181                  _dbus_socket_printable (socket_transport->fd));
182   
183   if (transport->connection == NULL)
184     return;
185
186   if (transport->disconnected)
187     {
188       _dbus_assert (socket_transport->read_watch == NULL);
189       return;
190     }
191   
192   _dbus_transport_ref (transport);
193
194   if (_dbus_transport_try_to_authenticate (transport))
195     need_read_watch =
196       (_dbus_counter_get_size_value (transport->live_messages) < transport->max_live_messages_size) &&
197       (_dbus_counter_get_unix_fd_value (transport->live_messages) < transport->max_live_messages_unix_fds);
198   else
199     {
200       if (transport->receive_credentials_pending)
201         need_read_watch = TRUE;
202       else
203         {
204           /* The reason to disable need_read_watch when not WAITING_FOR_INPUT
205            * is to avoid spinning on the file descriptor when we're waiting
206            * to write or for some other part of the auth process
207            */
208           DBusAuthState auth_state;
209           
210           auth_state = _dbus_auth_do_work (transport->auth);
211
212           /* If we need memory we install the read watch just in case,
213            * if there's no need for it, it will get de-installed
214            * next time we try reading. If we're authenticated we
215            * install it since we normally have it installed while
216            * authenticated.
217            */
218           if (auth_state == DBUS_AUTH_STATE_WAITING_FOR_INPUT ||
219               auth_state == DBUS_AUTH_STATE_WAITING_FOR_MEMORY ||
220               auth_state == DBUS_AUTH_STATE_AUTHENTICATED)
221             need_read_watch = TRUE;
222           else
223             need_read_watch = FALSE;
224         }
225     }
226
227   _dbus_verbose ("  setting read watch enabled = %d\n", need_read_watch);
228   _dbus_connection_toggle_watch_unlocked (transport->connection,
229                                           socket_transport->read_watch,
230                                           need_read_watch);
231
232   _dbus_transport_unref (transport);
233 }
234
235 static void
236 do_io_error (DBusTransport *transport)
237 {
238   _dbus_transport_ref (transport);
239   _dbus_transport_disconnect (transport);
240   _dbus_transport_unref (transport);
241 }
242
243 /* return value is whether we successfully read any new data. */
244 static dbus_bool_t
245 read_data_into_auth (DBusTransport *transport,
246                      dbus_bool_t   *oom)
247 {
248   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
249   DBusString *buffer;
250   int bytes_read;
251   int saved_errno;
252
253   *oom = FALSE;
254
255   _dbus_auth_get_buffer (transport->auth, &buffer);
256   
257   bytes_read = _dbus_read_socket (socket_transport->fd,
258                                   buffer, socket_transport->max_bytes_read_per_iteration);
259   saved_errno = _dbus_save_socket_errno ();
260
261   _dbus_auth_return_buffer (transport->auth, buffer);
262
263   if (bytes_read > 0)
264     {
265       _dbus_verbose (" read %d bytes in auth phase\n", bytes_read);
266
267       return TRUE;
268     }
269   else if (bytes_read < 0)
270     {
271       /* EINTR already handled for us */
272
273       if (_dbus_get_is_errno_enomem (saved_errno))
274         {
275           *oom = TRUE;
276         }
277       else if (_dbus_get_is_errno_eagain_or_ewouldblock (saved_errno))
278         ; /* do nothing, just return FALSE below */
279       else
280         {
281           _dbus_verbose ("Error reading from remote app: %s\n",
282                          _dbus_strerror (saved_errno));
283           do_io_error (transport);
284         }
285
286       return FALSE;
287     }
288   else
289     {
290       _dbus_assert (bytes_read == 0);
291       
292       _dbus_verbose ("Disconnected from remote app\n");
293       do_io_error (transport);
294
295       return FALSE;
296     }
297 }
298
299 /* Return value is whether we successfully wrote any bytes */
300 static dbus_bool_t
301 write_data_from_auth (DBusTransport *transport)
302 {
303   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
304   int bytes_written;
305   int saved_errno;
306   const DBusString *buffer;
307
308   if (!_dbus_auth_get_bytes_to_send (transport->auth,
309                                      &buffer))
310     return FALSE;
311   
312   bytes_written = _dbus_write_socket (socket_transport->fd,
313                                       buffer,
314                                       0, _dbus_string_get_length (buffer));
315   saved_errno = _dbus_save_socket_errno ();
316
317   if (bytes_written > 0)
318     {
319       _dbus_auth_bytes_sent (transport->auth, bytes_written);
320       return TRUE;
321     }
322   else if (bytes_written < 0)
323     {
324       /* EINTR already handled for us */
325       
326       if (_dbus_get_is_errno_eagain_or_ewouldblock (saved_errno))
327         ;
328       else
329         {
330           _dbus_verbose ("Error writing to remote app: %s\n",
331                          _dbus_strerror (saved_errno));
332           do_io_error (transport);
333         }
334     }
335
336   return FALSE;
337 }
338
339 /* FALSE on OOM */
340 static dbus_bool_t
341 exchange_credentials (DBusTransport *transport,
342                       dbus_bool_t    do_reading,
343                       dbus_bool_t    do_writing)
344 {
345   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
346   DBusError error = DBUS_ERROR_INIT;
347
348   _dbus_verbose ("exchange_credentials: do_reading = %d, do_writing = %d\n",
349                   do_reading, do_writing);
350
351   if (do_writing && transport->send_credentials_pending)
352     {
353       if (_dbus_send_credentials_socket (socket_transport->fd,
354                                          &error))
355         {
356           transport->send_credentials_pending = FALSE;
357         }
358       else
359         {
360           _dbus_verbose ("Failed to write credentials: %s\n", error.message);
361           dbus_error_free (&error);
362           do_io_error (transport);
363         }
364     }
365   
366   if (do_reading && transport->receive_credentials_pending)
367     {
368       /* FIXME this can fail due to IO error _or_ OOM, broken
369        * (somewhat tricky to fix since the OOM error can be set after
370        * we already read the credentials byte, so basically we need to
371        * separate reading the byte and storing it in the
372        * transport->credentials). Does not really matter for now
373        * because storing in credentials never actually fails on unix.
374        */      
375       if (_dbus_read_credentials_socket (socket_transport->fd,
376                                          transport->credentials,
377                                          &error))
378         {
379           transport->receive_credentials_pending = FALSE;
380         }
381       else
382         {
383           _dbus_verbose ("Failed to read credentials %s\n", error.message);
384           dbus_error_free (&error);
385           do_io_error (transport);
386         }
387     }
388
389   if (!(transport->send_credentials_pending ||
390         transport->receive_credentials_pending))
391     {
392       if (!_dbus_auth_set_credentials (transport->auth,
393                                        transport->credentials))
394         return FALSE;
395     }
396
397   return TRUE;
398 }
399
400 static dbus_bool_t
401 do_authentication (DBusTransport *transport,
402                    dbus_bool_t    do_reading,
403                    dbus_bool_t    do_writing,
404                    dbus_bool_t   *auth_completed)
405 {
406   dbus_bool_t oom;
407   dbus_bool_t orig_auth_state;
408
409   oom = FALSE;
410   
411   orig_auth_state = _dbus_transport_try_to_authenticate (transport);
412
413   /* This is essential to avoid the check_write_watch() at the end,
414    * we don't want to add a write watch in do_iteration before
415    * we try writing and get EAGAIN
416    */
417   if (orig_auth_state)
418     {
419       if (auth_completed)
420         *auth_completed = FALSE;
421       return TRUE;
422     }
423   
424   _dbus_transport_ref (transport);
425   
426   while (!_dbus_transport_try_to_authenticate (transport) &&
427          _dbus_transport_get_is_connected (transport))
428     {      
429       if (!exchange_credentials (transport, do_reading, do_writing))
430         {
431           /* OOM */
432           oom = TRUE;
433           goto out;
434         }
435       
436       if (transport->send_credentials_pending ||
437           transport->receive_credentials_pending)
438         {
439           _dbus_verbose ("send_credentials_pending = %d receive_credentials_pending = %d\n",
440                          transport->send_credentials_pending,
441                          transport->receive_credentials_pending);
442           goto out;
443         }
444
445 #define TRANSPORT_SIDE(t) ((t)->is_server ? "server" : "client")
446       switch (_dbus_auth_do_work (transport->auth))
447         {
448         case DBUS_AUTH_STATE_WAITING_FOR_INPUT:
449           _dbus_verbose (" %s auth state: waiting for input\n",
450                          TRANSPORT_SIDE (transport));
451           if (!do_reading || !read_data_into_auth (transport, &oom))
452             goto out;
453           break;
454       
455         case DBUS_AUTH_STATE_WAITING_FOR_MEMORY:
456           _dbus_verbose (" %s auth state: waiting for memory\n",
457                          TRANSPORT_SIDE (transport));
458           oom = TRUE;
459           goto out;
460           break;
461       
462         case DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND:
463           _dbus_verbose (" %s auth state: bytes to send\n",
464                          TRANSPORT_SIDE (transport));
465           if (!do_writing || !write_data_from_auth (transport))
466             goto out;
467           break;
468       
469         case DBUS_AUTH_STATE_NEED_DISCONNECT:
470           _dbus_verbose (" %s auth state: need to disconnect\n",
471                          TRANSPORT_SIDE (transport));
472           do_io_error (transport);
473           break;
474       
475         case DBUS_AUTH_STATE_AUTHENTICATED:
476           _dbus_verbose (" %s auth state: authenticated\n",
477                          TRANSPORT_SIDE (transport));
478           break;
479
480         case DBUS_AUTH_STATE_INVALID:
481           /* fall through */
482         default:
483           _dbus_assert_not_reached ("invalid auth state");
484         }
485     }
486
487  out:
488   if (auth_completed)
489     *auth_completed = (orig_auth_state != _dbus_transport_try_to_authenticate (transport));
490   
491   check_read_watch (transport);
492   check_write_watch (transport);
493   _dbus_transport_unref (transport);
494
495   if (oom)
496     return FALSE;
497   else
498     return TRUE;
499 }
500
501 /* returns false on oom */
502 static dbus_bool_t
503 do_writing (DBusTransport *transport)
504 {
505   int total;
506   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
507   dbus_bool_t oom;
508   
509   /* No messages without authentication! */
510   if (!_dbus_transport_try_to_authenticate (transport))
511     {
512       _dbus_verbose ("Not authenticated, not writing anything\n");
513       return TRUE;
514     }
515
516   if (transport->disconnected)
517     {
518       _dbus_verbose ("Not connected, not writing anything\n");
519       return TRUE;
520     }
521
522 #if 1
523   _dbus_verbose ("do_writing(), have_messages = %d, fd = %" DBUS_SOCKET_FORMAT "\n",
524                  _dbus_connection_has_messages_to_send_unlocked (transport->connection),
525                  _dbus_socket_printable (socket_transport->fd));
526 #endif
527   
528   oom = FALSE;
529   total = 0;
530
531   transport->overflowed = FALSE;
532
533   while (!transport->disconnected &&
534          _dbus_connection_has_messages_to_send_unlocked (transport->connection))
535     {
536       int bytes_written;
537       DBusMessage *message;
538       const DBusString *header;
539       const DBusString *body;
540       int header_len, body_len;
541       int total_bytes_to_write;
542       int saved_errno;
543       
544       if (total > socket_transport->max_bytes_written_per_iteration)
545         {
546           _dbus_verbose ("%d bytes exceeds %d bytes written per iteration, returning\n",
547                          total, socket_transport->max_bytes_written_per_iteration);
548           goto out;
549         }
550       
551       message = _dbus_connection_get_message_to_send (transport->connection);
552       _dbus_assert (message != NULL);
553       dbus_message_lock (message);
554
555 #if 0
556       _dbus_verbose ("writing message %p\n", message);
557 #endif
558       
559       _dbus_message_get_network_data (message,
560                                       &header, &body);
561
562       header_len = _dbus_string_get_length (header);
563       body_len = _dbus_string_get_length (body);
564
565       if (_dbus_auth_needs_encoding (transport->auth))
566         {
567           /* Does fd passing even make sense with encoded data? */
568           _dbus_assert(!DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport));
569
570           if (_dbus_string_get_length (&socket_transport->encoded_outgoing) == 0)
571             {
572               if (!_dbus_auth_encode_data (transport->auth,
573                                            header, &socket_transport->encoded_outgoing))
574                 {
575                   oom = TRUE;
576                   goto out;
577                 }
578               
579               if (!_dbus_auth_encode_data (transport->auth,
580                                            body, &socket_transport->encoded_outgoing))
581                 {
582                   _dbus_string_set_length (&socket_transport->encoded_outgoing, 0);
583                   oom = TRUE;
584                   goto out;
585                 }
586             }
587           
588           total_bytes_to_write = _dbus_string_get_length (&socket_transport->encoded_outgoing);
589
590 #if 0
591           _dbus_verbose ("encoded message is %d bytes\n",
592                          total_bytes_to_write);
593 #endif
594           
595           bytes_written =
596             _dbus_write_socket (socket_transport->fd,
597                                 &socket_transport->encoded_outgoing,
598                                 socket_transport->message_bytes_written,
599                                 total_bytes_to_write - socket_transport->message_bytes_written);
600           saved_errno = _dbus_save_socket_errno ();
601         }
602       else
603         {
604           total_bytes_to_write = header_len + body_len;
605
606 #if 0
607           _dbus_verbose ("message is %d bytes\n",
608                          total_bytes_to_write);
609 #endif
610
611 #ifdef HAVE_UNIX_FD_PASSING
612           if (socket_transport->message_bytes_written <= 0 && DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport))
613             {
614               /* Send the fds along with the first byte of the message */
615               const int *unix_fds;
616               unsigned n;
617
618               _dbus_message_get_unix_fds(message, &unix_fds, &n);
619
620               bytes_written =
621                 _dbus_write_socket_with_unix_fds_two (socket_transport->fd,
622                                                       header,
623                                                       socket_transport->message_bytes_written,
624                                                       header_len - socket_transport->message_bytes_written,
625                                                       body,
626                                                       0, body_len,
627                                                       unix_fds,
628                                                       n);
629               saved_errno = _dbus_save_socket_errno ();
630
631               if (bytes_written > 0 && n > 0)
632                 _dbus_verbose("Wrote %i unix fds\n", n);
633             }
634           else
635 #endif
636             {
637               if (socket_transport->message_bytes_written < header_len)
638                 {
639                   bytes_written =
640                     _dbus_write_socket_two (socket_transport->fd,
641                                             header,
642                                             socket_transport->message_bytes_written,
643                                             header_len - socket_transport->message_bytes_written,
644                                             body,
645                                             0, body_len);
646                 }
647               else
648                 {
649                   bytes_written =
650                     _dbus_write_socket (socket_transport->fd,
651                                         body,
652                                         (socket_transport->message_bytes_written - header_len),
653                                         body_len -
654                                         (socket_transport->message_bytes_written - header_len));
655                 }
656
657               saved_errno = _dbus_save_socket_errno ();
658             }
659         }
660
661       if (bytes_written < 0)
662         {
663           /* EINTR already handled for us */
664           
665           /* If the other end closed the socket with close() or shutdown(), we
666            * receive EPIPE here but we must not close the socket yet: there
667            * might still be some data to read. See:
668            * http://lists.freedesktop.org/archives/dbus/2008-March/009526.html
669            */
670           
671           if (_dbus_get_is_errno_eagain_or_ewouldblock (saved_errno) || _dbus_get_is_errno_epipe (saved_errno))
672             {
673               transport->overflowed = TRUE;
674               goto out;
675             }
676
677           /* Since Linux commit 25888e (from 2.6.37-rc4, Nov 2010), sendmsg()
678            * on Unix sockets returns -1 errno=ETOOMANYREFS when the passfd
679            * mechanism (SCM_RIGHTS) is used recursively with a recursion level
680            * of maximum 4. The kernel does not have an API to check whether
681            * the passed fds can be forwarded and it can change asynchronously.
682            * See:
683            * https://bugs.freedesktop.org/show_bug.cgi?id=80163
684            */
685
686           else if (_dbus_get_is_errno_etoomanyrefs (saved_errno))
687             {
688               /* We only send fds in the first byte of the message.
689                * ETOOMANYREFS cannot happen after.
690                */
691               _dbus_assert (socket_transport->message_bytes_written == 0);
692
693               _dbus_verbose (" discard message of %d bytes due to ETOOMANYREFS\n",
694                              total_bytes_to_write);
695
696               socket_transport->message_bytes_written = 0;
697               _dbus_string_set_length (&socket_transport->encoded_outgoing, 0);
698               _dbus_string_compact (&socket_transport->encoded_outgoing, 2048);
699
700               /* The message was not actually sent but it needs to be removed
701                * from the outgoing queue
702                */
703               _dbus_connection_message_sent_unlocked (transport->connection,
704                                                       message);
705             }
706           else
707             {
708               _dbus_verbose ("Error writing to remote app: %s\n",
709                              _dbus_strerror (saved_errno));
710               do_io_error (transport);
711               goto out;
712             }
713         }
714       else
715         {
716           _dbus_verbose (" wrote %d bytes of %d\n", bytes_written,
717                          total_bytes_to_write);
718           
719           total += bytes_written;
720           socket_transport->message_bytes_written += bytes_written;
721
722           _dbus_assert (socket_transport->message_bytes_written <=
723                         total_bytes_to_write);
724           
725           if (socket_transport->message_bytes_written == total_bytes_to_write)
726             {
727               socket_transport->message_bytes_written = 0;
728               _dbus_string_set_length (&socket_transport->encoded_outgoing, 0);
729               _dbus_string_compact (&socket_transport->encoded_outgoing, 2048);
730
731               _dbus_connection_message_sent_unlocked (transport->connection,
732                                                       message);
733             }
734         }
735     }
736
737  out:
738   if (oom)
739     return FALSE;
740   else
741     return TRUE;
742 }
743
744 /* returns false on out-of-memory */
745 static dbus_bool_t
746 do_reading (DBusTransport *transport)
747 {
748   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
749   DBusString *buffer;
750   int bytes_read;
751   int total;
752   dbus_bool_t oom;
753   int saved_errno;
754
755   _dbus_verbose ("fd = %" DBUS_SOCKET_FORMAT "\n",
756                  _dbus_socket_printable (socket_transport->fd));
757   
758   /* No messages without authentication! */
759   if (!_dbus_transport_try_to_authenticate (transport))
760     return TRUE;
761
762   oom = FALSE;
763   
764   total = 0;
765
766  again:
767   
768   /* See if we've exceeded max messages and need to disable reading */
769   check_read_watch (transport);
770   
771   if (total > socket_transport->max_bytes_read_per_iteration)
772     {
773       _dbus_verbose ("%d bytes exceeds %d bytes read per iteration, returning\n",
774                      total, socket_transport->max_bytes_read_per_iteration);
775       goto out;
776     }
777
778   _dbus_assert (socket_transport->read_watch != NULL ||
779                 transport->disconnected);
780   
781   if (transport->disconnected)
782     goto out;
783
784   if (!dbus_watch_get_enabled (socket_transport->read_watch))
785     return TRUE;
786   
787   if (_dbus_auth_needs_decoding (transport->auth))
788     {
789       /* Does fd passing even make sense with encoded data? */
790       _dbus_assert(!DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport));
791
792       if (_dbus_string_get_length (&socket_transport->encoded_incoming) > 0)
793         bytes_read = _dbus_string_get_length (&socket_transport->encoded_incoming);
794       else
795         bytes_read = _dbus_read_socket (socket_transport->fd,
796                                         &socket_transport->encoded_incoming,
797                                         socket_transport->max_bytes_read_per_iteration);
798
799       saved_errno = _dbus_save_socket_errno ();
800
801       _dbus_assert (_dbus_string_get_length (&socket_transport->encoded_incoming) ==
802                     bytes_read);
803       
804       if (bytes_read > 0)
805         {
806           _dbus_message_loader_get_buffer (transport->loader,
807                                            &buffer,
808                                            NULL,
809                                            NULL);
810
811           if (!_dbus_auth_decode_data (transport->auth,
812                                        &socket_transport->encoded_incoming,
813                                        buffer))
814             {
815               _dbus_verbose ("Out of memory decoding incoming data\n");
816               _dbus_message_loader_return_buffer (transport->loader,
817                                               buffer);
818
819               oom = TRUE;
820               goto out;
821             }
822
823           _dbus_message_loader_return_buffer (transport->loader,
824                                               buffer);
825
826           _dbus_string_set_length (&socket_transport->encoded_incoming, 0);
827           _dbus_string_compact (&socket_transport->encoded_incoming, 2048);
828         }
829     }
830   else
831     {
832       int max_to_read = DBUS_MAXIMUM_MESSAGE_LENGTH;
833       dbus_bool_t may_read_unix_fds = TRUE;
834
835       _dbus_message_loader_get_buffer (transport->loader,
836                                        &buffer,
837                                        &max_to_read,
838                                        &may_read_unix_fds);
839
840       if (max_to_read > socket_transport->max_bytes_read_per_iteration)
841         max_to_read = socket_transport->max_bytes_read_per_iteration;
842
843 #ifdef HAVE_UNIX_FD_PASSING
844       if (DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport) && may_read_unix_fds)
845         {
846           int *fds;
847           unsigned int n_fds;
848
849           if (!_dbus_message_loader_get_unix_fds(transport->loader, &fds, &n_fds))
850             {
851               _dbus_verbose ("Out of memory reading file descriptors\n");
852               _dbus_message_loader_return_buffer (transport->loader, buffer);
853               oom = TRUE;
854               goto out;
855             }
856
857           bytes_read = _dbus_read_socket_with_unix_fds(socket_transport->fd,
858                                                        buffer,
859                                                        max_to_read,
860                                                        fds, &n_fds);
861           saved_errno = _dbus_save_socket_errno ();
862
863           if (bytes_read >= 0 && n_fds > 0)
864             _dbus_verbose("Read %i unix fds\n", n_fds);
865
866           _dbus_message_loader_return_unix_fds(transport->loader, fds, bytes_read < 0 ? 0 : n_fds);
867         }
868       else
869 #endif
870         {
871           bytes_read = _dbus_read_socket (socket_transport->fd,
872                                           buffer, max_to_read);
873           saved_errno = _dbus_save_socket_errno ();
874         }
875
876       _dbus_message_loader_return_buffer (transport->loader,
877                                           buffer);
878     }
879
880   if (bytes_read < 0)
881     {
882       /* EINTR already handled for us */
883
884       if (_dbus_get_is_errno_enomem (saved_errno))
885         {
886           _dbus_verbose ("Out of memory in read()/do_reading()\n");
887           oom = TRUE;
888           goto out;
889         }
890       else if (_dbus_get_is_errno_eagain_or_ewouldblock (saved_errno))
891         goto out;
892       else
893         {
894           _dbus_verbose ("Error reading from remote app: %s\n",
895                          _dbus_strerror (saved_errno));
896           do_io_error (transport);
897           goto out;
898         }
899     }
900   else if (bytes_read == 0)
901     {
902       _dbus_verbose ("Disconnected from remote app\n");
903       do_io_error (transport);
904       goto out;
905     }
906   else
907     {
908       _dbus_verbose (" read %d bytes\n", bytes_read);
909       
910       total += bytes_read;      
911
912       if (!_dbus_transport_queue_messages (transport))
913         {
914           oom = TRUE;
915           _dbus_verbose (" out of memory when queueing messages we just read in the transport\n");
916           goto out;
917         }
918       
919       /* Try reading more data until we get EAGAIN and return, or
920        * exceed max bytes per iteration.  If in blocking mode of
921        * course we'll block instead of returning.
922        */
923       goto again;
924     }
925
926  out:
927   if (oom)
928     return FALSE;
929   else
930     return TRUE;
931 }
932
933 static dbus_bool_t
934 unix_error_with_read_to_come (DBusTransport *itransport,
935                               DBusWatch     *watch,
936                               unsigned int   flags)
937 {
938   DBusTransportSocket *transport = (DBusTransportSocket *) itransport;
939
940   if (!(flags & DBUS_WATCH_HANGUP || flags & DBUS_WATCH_ERROR))
941     return FALSE;
942    
943   /* If we have a read watch enabled ...
944      we -might have data incoming ... => handle the HANGUP there */
945   if (watch != transport->read_watch &&
946       _dbus_watch_get_enabled (transport->read_watch))
947     return FALSE;
948       
949   return TRUE; 
950 }
951
952 static dbus_bool_t
953 socket_handle_watch (DBusTransport *transport,
954                    DBusWatch     *watch,
955                    unsigned int   flags)
956 {
957   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
958
959   _dbus_assert (watch == socket_transport->read_watch ||
960                 watch == socket_transport->write_watch);
961   _dbus_assert (watch != NULL);
962   
963   /* If we hit an error here on a write watch, don't disconnect the transport yet because data can
964    * still be in the buffer and do_reading may need several iteration to read
965    * it all (because of its max_bytes_read_per_iteration limit). 
966    */
967   if (!(flags & DBUS_WATCH_READABLE) && unix_error_with_read_to_come (transport, watch, flags))
968     {
969       _dbus_verbose ("Hang up or error on watch\n");
970       _dbus_transport_disconnect (transport);
971       return TRUE;
972     }
973   
974   if (watch == socket_transport->read_watch &&
975       (flags & DBUS_WATCH_READABLE))
976     {
977       dbus_bool_t auth_finished;
978 #if 1
979       _dbus_verbose ("handling read watch %p flags = %x\n",
980                      watch, flags);
981 #endif
982       if (!do_authentication (transport, TRUE, FALSE, &auth_finished))
983         return FALSE;
984
985       /* We don't want to do a read immediately following
986        * a successful authentication.  This is so we
987        * have a chance to propagate the authentication
988        * state further up.  Specifically, we need to
989        * process any pending data from the auth object.
990        */
991       if (!auth_finished)
992         {
993           if (!do_reading (transport))
994             {
995               _dbus_verbose ("no memory to read\n");
996               return FALSE;
997             }
998         }
999       else
1000         {
1001           _dbus_verbose ("Not reading anything since we just completed the authentication\n");
1002         }
1003     }
1004   else if (watch == socket_transport->write_watch &&
1005            (flags & DBUS_WATCH_WRITABLE))
1006     {
1007 #if 1
1008       _dbus_verbose ("handling write watch, have_outgoing_messages = %d\n",
1009                      _dbus_connection_has_messages_to_send_unlocked (transport->connection));
1010 #endif
1011       if (!do_authentication (transport, FALSE, TRUE, NULL))
1012         return FALSE;
1013       
1014       if (!do_writing (transport))
1015         {
1016           _dbus_verbose ("no memory to write\n");
1017           return FALSE;
1018         }
1019
1020       /* See if we still need the write watch */
1021       check_write_watch (transport);
1022     }
1023 #ifdef DBUS_ENABLE_VERBOSE_MODE
1024   else
1025     {
1026       if (watch == socket_transport->read_watch)
1027         _dbus_verbose ("asked to handle read watch with non-read condition 0x%x\n",
1028                        flags);
1029       else if (watch == socket_transport->write_watch)
1030         _dbus_verbose ("asked to handle write watch with non-write condition 0x%x\n",
1031                        flags);
1032       else
1033         _dbus_verbose ("asked to handle watch %p on fd %" DBUS_SOCKET_FORMAT " that we don't recognize\n",
1034                        watch, _dbus_socket_printable (_dbus_watch_get_socket (watch)));
1035     }
1036 #endif /* DBUS_ENABLE_VERBOSE_MODE */
1037
1038   return TRUE;
1039 }
1040
1041 static void
1042 socket_disconnect (DBusTransport *transport)
1043 {
1044   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
1045
1046   _dbus_verbose ("\n");
1047   
1048   free_watches (transport);
1049   
1050   _dbus_close_socket (socket_transport->fd, NULL);
1051   _dbus_socket_invalidate (&socket_transport->fd);
1052 }
1053
1054 static dbus_bool_t
1055 socket_connection_set (DBusTransport *transport)
1056 {
1057   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
1058
1059   _dbus_watch_set_handler (socket_transport->write_watch,
1060                            _dbus_connection_handle_watch,
1061                            transport->connection, NULL);
1062
1063   _dbus_watch_set_handler (socket_transport->read_watch,
1064                            _dbus_connection_handle_watch,
1065                            transport->connection, NULL);
1066   
1067   if (!_dbus_connection_add_watch_unlocked (transport->connection,
1068                                             socket_transport->write_watch))
1069     return FALSE;
1070
1071   if (!_dbus_connection_add_watch_unlocked (transport->connection,
1072                                             socket_transport->read_watch))
1073     {
1074       _dbus_connection_remove_watch_unlocked (transport->connection,
1075                                               socket_transport->write_watch);
1076       return FALSE;
1077     }
1078
1079   check_read_watch (transport);
1080   check_write_watch (transport);
1081
1082   return TRUE;
1083 }
1084
1085 /**
1086  * @todo We need to have a way to wake up the select sleep if
1087  * a new iteration request comes in with a flag (read/write) that
1088  * we're not currently serving. Otherwise a call that just reads
1089  * could block a write call forever (if there are no incoming
1090  * messages).
1091  */
1092 static  void
1093 socket_do_iteration (DBusTransport *transport,
1094                    unsigned int   flags,
1095                    int            timeout_milliseconds)
1096 {
1097   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
1098   DBusPollFD poll_fd;
1099   int poll_res;
1100   int poll_timeout;
1101
1102   _dbus_verbose (" iteration flags = %s%s timeout = %d read_watch = %p write_watch = %p fd = %" DBUS_SOCKET_FORMAT "\n",
1103                  flags & DBUS_ITERATION_DO_READING ? "read" : "",
1104                  flags & DBUS_ITERATION_DO_WRITING ? "write" : "",
1105                  timeout_milliseconds,
1106                  socket_transport->read_watch,
1107                  socket_transport->write_watch,
1108                  _dbus_socket_printable (socket_transport->fd));
1109   
1110   /* the passed in DO_READING/DO_WRITING flags indicate whether to
1111    * read/write messages, but regardless of those we may need to block
1112    * for reading/writing to do auth.  But if we do reading for auth,
1113    * we don't want to read any messages yet if not given DO_READING.
1114    */
1115
1116   poll_fd.fd = _dbus_socket_get_pollable (socket_transport->fd);
1117   poll_fd.events = 0;
1118   
1119   if (_dbus_transport_try_to_authenticate (transport))
1120     {
1121       /* This is kind of a hack; if we have stuff to write, then try
1122        * to avoid the poll. This is probably about a 5% speedup on an
1123        * echo client/server.
1124        *
1125        * If both reading and writing were requested, we want to avoid this
1126        * since it could have funky effects:
1127        *   - both ends spinning waiting for the other one to read
1128        *     data so they can finish writing
1129        *   - prioritizing all writing ahead of reading
1130        */
1131       if ((flags & DBUS_ITERATION_DO_WRITING) &&
1132           !(flags & (DBUS_ITERATION_DO_READING | DBUS_ITERATION_BLOCK)) &&
1133           !transport->disconnected &&
1134           _dbus_connection_has_messages_to_send_unlocked (transport->connection))
1135         {
1136           do_writing (transport);
1137
1138           if (transport->disconnected ||
1139               !_dbus_connection_has_messages_to_send_unlocked (transport->connection))
1140             goto out;
1141         }
1142
1143       /* If we get here, we decided to do the poll() after all */
1144       _dbus_assert (socket_transport->read_watch);
1145       if (flags & DBUS_ITERATION_DO_READING)
1146         poll_fd.events |= _DBUS_POLLIN;
1147
1148       _dbus_assert (socket_transport->write_watch);
1149       if (flags & DBUS_ITERATION_DO_WRITING)
1150         poll_fd.events |= _DBUS_POLLOUT;
1151     }
1152   else
1153     {
1154       DBusAuthState auth_state;
1155       
1156       auth_state = _dbus_auth_do_work (transport->auth);
1157
1158       if (transport->receive_credentials_pending ||
1159           auth_state == DBUS_AUTH_STATE_WAITING_FOR_INPUT)
1160         poll_fd.events |= _DBUS_POLLIN;
1161
1162       if (transport->send_credentials_pending ||
1163           auth_state == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND)
1164         poll_fd.events |= _DBUS_POLLOUT;
1165     }
1166
1167   if (poll_fd.events)
1168     {
1169       int saved_errno;
1170
1171       if (flags & DBUS_ITERATION_BLOCK)
1172         poll_timeout = timeout_milliseconds;
1173       else
1174         poll_timeout = 0;
1175
1176       /* For blocking selects we drop the connection lock here
1177        * to avoid blocking out connection access during a potentially
1178        * indefinite blocking call. The io path is still protected
1179        * by the io_path_cond condvar, so we won't reenter this.
1180        */
1181       if (flags & DBUS_ITERATION_BLOCK)
1182         {
1183           _dbus_verbose ("unlock pre poll\n");
1184           _dbus_connection_unlock (transport->connection);
1185         }
1186       
1187     again:
1188       poll_res = _dbus_poll (&poll_fd, 1, poll_timeout);
1189       saved_errno = _dbus_save_socket_errno ();
1190
1191       if (poll_res < 0 && _dbus_get_is_errno_eintr (saved_errno))
1192         goto again;
1193
1194       if (flags & DBUS_ITERATION_BLOCK)
1195         {
1196           _dbus_verbose ("lock post poll\n");
1197           _dbus_connection_lock (transport->connection);
1198         }
1199       
1200       if (poll_res >= 0)
1201         {
1202           if (poll_res == 0)
1203             poll_fd.revents = 0; /* some concern that posix does not guarantee this;
1204                                   * valgrind flags it as an error. though it probably
1205                                   * is guaranteed on linux at least.
1206                                   */
1207           
1208           if (poll_fd.revents & _DBUS_POLLERR)
1209             do_io_error (transport);
1210           else
1211             {
1212               dbus_bool_t need_read = (poll_fd.revents & _DBUS_POLLIN) > 0;
1213               dbus_bool_t need_write = (poll_fd.revents & _DBUS_POLLOUT) > 0;
1214               dbus_bool_t authentication_completed;
1215
1216               _dbus_verbose ("in iteration, need_read=%d need_write=%d\n",
1217                              need_read, need_write);
1218               do_authentication (transport, need_read, need_write,
1219                                  &authentication_completed);
1220
1221               /* See comment in socket_handle_watch. */
1222               if (authentication_completed)
1223                 goto out;
1224                                  
1225               if (need_read && (flags & DBUS_ITERATION_DO_READING))
1226                 do_reading (transport);
1227               if (need_write && (flags & DBUS_ITERATION_DO_WRITING))
1228                 do_writing (transport);
1229             }
1230         }
1231       else
1232         {
1233           _dbus_verbose ("Error from _dbus_poll(): %s\n",
1234                          _dbus_strerror (saved_errno));
1235         }
1236     }
1237
1238
1239  out:
1240   /* We need to install the write watch only if we did not
1241    * successfully write everything. Note we need to be careful that we
1242    * don't call check_write_watch *before* do_writing, since it's
1243    * inefficient to add the write watch, and we can avoid it most of
1244    * the time since we can write immediately.
1245    * 
1246    * However, we MUST always call check_write_watch(); DBusConnection code
1247    * relies on the fact that running an iteration will notice that
1248    * messages are pending.
1249    */
1250   check_write_watch (transport);
1251
1252   _dbus_verbose (" ... leaving do_iteration()\n");
1253 }
1254
1255 static void
1256 socket_live_messages_changed (DBusTransport *transport)
1257 {
1258   /* See if we should look for incoming messages again */
1259   check_read_watch (transport);
1260 }
1261
1262
1263 static dbus_bool_t
1264 socket_get_socket_fd (DBusTransport *transport,
1265                       DBusSocket    *fd_p)
1266 {
1267   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
1268   
1269   *fd_p = socket_transport->fd;
1270   
1271   return TRUE;
1272 }
1273
1274 static const DBusTransportVTable socket_vtable = {
1275   socket_finalize,
1276   socket_handle_watch,
1277   socket_disconnect,
1278   socket_connection_set,
1279   socket_do_iteration,
1280   socket_live_messages_changed,
1281   socket_get_socket_fd
1282 };
1283
1284 /**
1285  * Creates a new transport for the given socket file descriptor.  The file
1286  * descriptor must be nonblocking (use _dbus_set_fd_nonblocking() to
1287  * make it so). This function is shared by various transports that
1288  * boil down to a full duplex file descriptor.
1289  *
1290  * @param fd the file descriptor.
1291  * @param server_guid non-#NULL if this transport is on the server side of a connection
1292  * @param address the transport's address
1293  * @returns the new transport, or #NULL if no memory.
1294  */
1295 DBusTransport*
1296 _dbus_transport_new_for_socket (DBusSocket        fd,
1297                                 const DBusString *server_guid,
1298                                 const DBusString *address)
1299 {
1300   DBusTransportSocket *socket_transport;
1301   
1302   socket_transport = dbus_new0 (DBusTransportSocket, 1);
1303   if (socket_transport == NULL)
1304     return NULL;
1305
1306   if (!_dbus_string_init (&socket_transport->encoded_outgoing))
1307     goto failed_0;
1308
1309   if (!_dbus_string_init (&socket_transport->encoded_incoming))
1310     goto failed_1;
1311   
1312   socket_transport->write_watch = _dbus_watch_new (_dbus_socket_get_pollable (fd),
1313                                                  DBUS_WATCH_WRITABLE,
1314                                                  FALSE,
1315                                                  NULL, NULL, NULL);
1316   if (socket_transport->write_watch == NULL)
1317     goto failed_2;
1318   
1319   socket_transport->read_watch = _dbus_watch_new (_dbus_socket_get_pollable (fd),
1320                                                 DBUS_WATCH_READABLE,
1321                                                 FALSE,
1322                                                 NULL, NULL, NULL);
1323   if (socket_transport->read_watch == NULL)
1324     goto failed_3;
1325
1326   if (!_dbus_transport_init_base (&socket_transport->base,
1327                                   &socket_vtable,
1328                                   server_guid, address))
1329     goto failed_4;
1330
1331 #ifdef HAVE_UNIX_FD_PASSING
1332   _dbus_auth_set_unix_fd_possible(socket_transport->base.auth, _dbus_socket_can_pass_unix_fd(fd));
1333 #endif
1334
1335   socket_transport->fd = fd;
1336   socket_transport->message_bytes_written = 0;
1337   
1338   /* These values should probably be tunable or something. */     
1339   socket_transport->max_bytes_read_per_iteration = 2048;
1340   socket_transport->max_bytes_written_per_iteration = 2048;
1341   
1342   return (DBusTransport*) socket_transport;
1343
1344  failed_4:
1345   _dbus_watch_invalidate (socket_transport->read_watch);
1346   _dbus_watch_unref (socket_transport->read_watch);
1347  failed_3:
1348   _dbus_watch_invalidate (socket_transport->write_watch);
1349   _dbus_watch_unref (socket_transport->write_watch);
1350  failed_2:
1351   _dbus_string_free (&socket_transport->encoded_incoming);
1352  failed_1:
1353   _dbus_string_free (&socket_transport->encoded_outgoing);
1354  failed_0:
1355   dbus_free (socket_transport);
1356   return NULL;
1357 }
1358
1359 /**
1360  * Creates a new transport for the given hostname and port.
1361  * If host is NULL, it will default to localhost
1362  *
1363  * @param host the host to connect to
1364  * @param port the port to connect to
1365  * @param family the address family to connect to
1366  * @param noncefile path to nonce file
1367  * @param error location to store reason for failure.
1368  * @returns a new transport, or #NULL on failure.
1369  */
1370 DBusTransport*
1371 _dbus_transport_new_for_tcp_socket (const char     *host,
1372                                     const char     *port,
1373                                     const char     *family,
1374                                     const char     *noncefile,
1375                                     DBusError      *error)
1376 {
1377   DBusSocket fd;
1378   DBusTransport *transport;
1379   DBusString address;
1380   
1381   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1382
1383   if (!_dbus_string_init (&address))
1384     {
1385       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1386       return NULL;
1387     }
1388
1389   if (host == NULL)
1390     host = "localhost";
1391
1392   if (!_dbus_string_append (&address, noncefile ? "nonce-tcp:" : "tcp:"))
1393     goto error;
1394
1395   if (!_dbus_string_append (&address, "host=") ||
1396       !_dbus_string_append (&address, host))
1397     goto error;
1398
1399   if (!_dbus_string_append (&address, ",port=") ||
1400       !_dbus_string_append (&address, port))
1401     goto error;
1402
1403   if (family != NULL &&
1404       (!_dbus_string_append (&address, ",family=") ||
1405        !_dbus_string_append (&address, family)))
1406     goto error;
1407
1408   if (noncefile != NULL &&
1409       (!_dbus_string_append (&address, ",noncefile=") ||
1410        !_dbus_string_append (&address, noncefile)))
1411     goto error;
1412
1413   fd = _dbus_connect_tcp_socket_with_nonce (host, port, family, noncefile, error);
1414   if (!_dbus_socket_is_valid (fd))
1415     {
1416       _DBUS_ASSERT_ERROR_IS_SET (error);
1417       _dbus_string_free (&address);
1418       return NULL;
1419     }
1420
1421   _dbus_verbose ("Successfully connected to tcp socket %s:%s\n",
1422                  host, port);
1423   
1424   transport = _dbus_transport_new_for_socket (fd, NULL, &address);
1425   _dbus_string_free (&address);
1426   if (transport == NULL)
1427     {
1428       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1429       _dbus_close_socket (fd, NULL);
1430       _dbus_socket_invalidate (&fd);
1431     }
1432
1433   return transport;
1434
1435 error:
1436   _dbus_string_free (&address);
1437   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1438   return NULL;
1439 }
1440
1441 /**
1442  * Opens a TCP socket transport.
1443  * 
1444  * @param entry the address entry to try opening as a tcp transport.
1445  * @param transport_p return location for the opened transport
1446  * @param error error to be set
1447  * @returns result of the attempt
1448  */
1449 DBusTransportOpenResult
1450 _dbus_transport_open_socket(DBusAddressEntry  *entry,
1451                             DBusTransport    **transport_p,                            
1452                             DBusError         *error)
1453 {
1454   const char *method;
1455   dbus_bool_t isTcp;
1456   dbus_bool_t isNonceTcp;
1457   
1458   method = dbus_address_entry_get_method (entry);
1459   _dbus_assert (method != NULL);
1460
1461   isTcp = strcmp (method, "tcp") == 0;
1462   isNonceTcp = strcmp (method, "nonce-tcp") == 0;
1463
1464   if (isTcp || isNonceTcp)
1465     {
1466       const char *host = dbus_address_entry_get_value (entry, "host");
1467       const char *port = dbus_address_entry_get_value (entry, "port");
1468       const char *family = dbus_address_entry_get_value (entry, "family");
1469       const char *noncefile = dbus_address_entry_get_value (entry, "noncefile");
1470
1471       if ((isNonceTcp == TRUE) != (noncefile != NULL)) {
1472           _dbus_set_bad_address (error, method, "noncefile", NULL);
1473           return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
1474       }
1475
1476       if (port == NULL)
1477         {
1478           _dbus_set_bad_address (error, method, "port", NULL);
1479           return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
1480         }
1481
1482       *transport_p = _dbus_transport_new_for_tcp_socket (host, port, family, noncefile, error);
1483       if (*transport_p == NULL)
1484         {
1485           _DBUS_ASSERT_ERROR_IS_SET (error);
1486           return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
1487         }
1488       else
1489         {
1490           _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1491           return DBUS_TRANSPORT_OPEN_OK;
1492         }
1493     }
1494   else
1495     {
1496       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1497       return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
1498     }
1499 }
1500
1501 /** @} */
1502