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