D-Bus  1.4.18
dbus-transport-socket.c
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-transport-socket.c  Socket subclasses of DBusTransport
00003  *
00004  * Copyright (C) 2002, 2003, 2004, 2006  Red Hat Inc.
00005  *
00006  * Licensed under the Academic Free License version 2.1
00007  * 
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  * 
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00021  *
00022  */
00023 
00024 #include <config.h>
00025 #include "dbus-internals.h"
00026 #include "dbus-connection-internal.h"
00027 #include "dbus-nonce.h"
00028 #include "dbus-transport-socket.h"
00029 #include "dbus-transport-protected.h"
00030 #include "dbus-watch.h"
00031 #include "dbus-credentials.h"
00032 
00044 typedef struct DBusTransportSocket DBusTransportSocket;
00045 
00049 struct DBusTransportSocket
00050 {
00051   DBusTransport base;                   
00052   int fd;                               
00053   DBusWatch *read_watch;                
00054   DBusWatch *write_watch;               
00056   int max_bytes_read_per_iteration;     
00057   int max_bytes_written_per_iteration;  
00059   int message_bytes_written;            
00063   DBusString encoded_outgoing;          
00066   DBusString encoded_incoming;          
00069 };
00070 
00071 static void
00072 free_watches (DBusTransport *transport)
00073 {
00074   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
00075 
00076   _dbus_verbose ("start\n");
00077   
00078   if (socket_transport->read_watch)
00079     {
00080       if (transport->connection)
00081         _dbus_connection_remove_watch_unlocked (transport->connection,
00082                                                 socket_transport->read_watch);
00083       _dbus_watch_invalidate (socket_transport->read_watch);
00084       _dbus_watch_unref (socket_transport->read_watch);
00085       socket_transport->read_watch = NULL;
00086     }
00087 
00088   if (socket_transport->write_watch)
00089     {
00090       if (transport->connection)
00091         _dbus_connection_remove_watch_unlocked (transport->connection,
00092                                                 socket_transport->write_watch);
00093       _dbus_watch_invalidate (socket_transport->write_watch);
00094       _dbus_watch_unref (socket_transport->write_watch);
00095       socket_transport->write_watch = NULL;
00096     }
00097 
00098   _dbus_verbose ("end\n");
00099 }
00100 
00101 static void
00102 socket_finalize (DBusTransport *transport)
00103 {
00104   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
00105 
00106   _dbus_verbose ("\n");
00107   
00108   free_watches (transport);
00109 
00110   _dbus_string_free (&socket_transport->encoded_outgoing);
00111   _dbus_string_free (&socket_transport->encoded_incoming);
00112   
00113   _dbus_transport_finalize_base (transport);
00114 
00115   _dbus_assert (socket_transport->read_watch == NULL);
00116   _dbus_assert (socket_transport->write_watch == NULL);
00117   
00118   dbus_free (transport);
00119 }
00120 
00121 static void
00122 check_write_watch (DBusTransport *transport)
00123 {
00124   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
00125   dbus_bool_t needed;
00126 
00127   if (transport->connection == NULL)
00128     return;
00129 
00130   if (transport->disconnected)
00131     {
00132       _dbus_assert (socket_transport->write_watch == NULL);
00133       return;
00134     }
00135   
00136   _dbus_transport_ref (transport);
00137 
00138   if (_dbus_transport_get_is_authenticated (transport))
00139     needed = _dbus_connection_has_messages_to_send_unlocked (transport->connection);
00140   else
00141     {
00142       if (transport->send_credentials_pending)
00143         needed = TRUE;
00144       else
00145         {
00146           DBusAuthState auth_state;
00147           
00148           auth_state = _dbus_auth_do_work (transport->auth);
00149           
00150           /* If we need memory we install the write watch just in case,
00151            * if there's no need for it, it will get de-installed
00152            * next time we try reading.
00153            */
00154           if (auth_state == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND ||
00155               auth_state == DBUS_AUTH_STATE_WAITING_FOR_MEMORY)
00156             needed = TRUE;
00157           else
00158             needed = FALSE;
00159         }
00160     }
00161 
00162   _dbus_verbose ("check_write_watch(): needed = %d on connection %p watch %p fd = %d outgoing messages exist %d\n",
00163                  needed, transport->connection, socket_transport->write_watch,
00164                  socket_transport->fd,
00165                  _dbus_connection_has_messages_to_send_unlocked (transport->connection));
00166 
00167   _dbus_connection_toggle_watch_unlocked (transport->connection,
00168                                           socket_transport->write_watch,
00169                                           needed);
00170 
00171   _dbus_transport_unref (transport);
00172 }
00173 
00174 static void
00175 check_read_watch (DBusTransport *transport)
00176 {
00177   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
00178   dbus_bool_t need_read_watch;
00179 
00180   _dbus_verbose ("fd = %d\n",socket_transport->fd);
00181   
00182   if (transport->connection == NULL)
00183     return;
00184 
00185   if (transport->disconnected)
00186     {
00187       _dbus_assert (socket_transport->read_watch == NULL);
00188       return;
00189     }
00190   
00191   _dbus_transport_ref (transport);
00192 
00193   if (_dbus_transport_get_is_authenticated (transport))
00194     need_read_watch =
00195       (_dbus_counter_get_size_value (transport->live_messages) < transport->max_live_messages_size) &&
00196       (_dbus_counter_get_unix_fd_value (transport->live_messages) < transport->max_live_messages_unix_fds);
00197   else
00198     {
00199       if (transport->receive_credentials_pending)
00200         need_read_watch = TRUE;
00201       else
00202         {
00203           /* The reason to disable need_read_watch when not WAITING_FOR_INPUT
00204            * is to avoid spinning on the file descriptor when we're waiting
00205            * to write or for some other part of the auth process
00206            */
00207           DBusAuthState auth_state;
00208           
00209           auth_state = _dbus_auth_do_work (transport->auth);
00210 
00211           /* If we need memory we install the read watch just in case,
00212            * if there's no need for it, it will get de-installed
00213            * next time we try reading. If we're authenticated we
00214            * install it since we normally have it installed while
00215            * authenticated.
00216            */
00217           if (auth_state == DBUS_AUTH_STATE_WAITING_FOR_INPUT ||
00218               auth_state == DBUS_AUTH_STATE_WAITING_FOR_MEMORY ||
00219               auth_state == DBUS_AUTH_STATE_AUTHENTICATED)
00220             need_read_watch = TRUE;
00221           else
00222             need_read_watch = FALSE;
00223         }
00224     }
00225 
00226   _dbus_verbose ("  setting read watch enabled = %d\n", need_read_watch);
00227   _dbus_connection_toggle_watch_unlocked (transport->connection,
00228                                           socket_transport->read_watch,
00229                                           need_read_watch);
00230 
00231   _dbus_transport_unref (transport);
00232 }
00233 
00234 static void
00235 do_io_error (DBusTransport *transport)
00236 {
00237   _dbus_transport_ref (transport);
00238   _dbus_transport_disconnect (transport);
00239   _dbus_transport_unref (transport);
00240 }
00241 
00242 /* return value is whether we successfully read any new data. */
00243 static dbus_bool_t
00244 read_data_into_auth (DBusTransport *transport,
00245                      dbus_bool_t   *oom)
00246 {
00247   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
00248   DBusString *buffer;
00249   int bytes_read;
00250   
00251   *oom = FALSE;
00252 
00253   _dbus_auth_get_buffer (transport->auth, &buffer);
00254   
00255   bytes_read = _dbus_read_socket (socket_transport->fd,
00256                                   buffer, socket_transport->max_bytes_read_per_iteration);
00257 
00258   _dbus_auth_return_buffer (transport->auth, buffer,
00259                             bytes_read > 0 ? bytes_read : 0);
00260 
00261   if (bytes_read > 0)
00262     {
00263       _dbus_verbose (" read %d bytes in auth phase\n", bytes_read);
00264 
00265       return TRUE;
00266     }
00267   else if (bytes_read < 0)
00268     {
00269       /* EINTR already handled for us */
00270 
00271       if (_dbus_get_is_errno_enomem ())
00272         {
00273           *oom = TRUE;
00274         }
00275       else if (_dbus_get_is_errno_eagain_or_ewouldblock ())
00276         ; /* do nothing, just return FALSE below */
00277       else
00278         {
00279           _dbus_verbose ("Error reading from remote app: %s\n",
00280                          _dbus_strerror_from_errno ());
00281           do_io_error (transport);
00282         }
00283 
00284       return FALSE;
00285     }
00286   else
00287     {
00288       _dbus_assert (bytes_read == 0);
00289       
00290       _dbus_verbose ("Disconnected from remote app\n");
00291       do_io_error (transport);
00292 
00293       return FALSE;
00294     }
00295 }
00296 
00297 /* Return value is whether we successfully wrote any bytes */
00298 static dbus_bool_t
00299 write_data_from_auth (DBusTransport *transport)
00300 {
00301   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
00302   int bytes_written;
00303   const DBusString *buffer;
00304 
00305   if (!_dbus_auth_get_bytes_to_send (transport->auth,
00306                                      &buffer))
00307     return FALSE;
00308   
00309   bytes_written = _dbus_write_socket (socket_transport->fd,
00310                                       buffer,
00311                                       0, _dbus_string_get_length (buffer));
00312 
00313   if (bytes_written > 0)
00314     {
00315       _dbus_auth_bytes_sent (transport->auth, bytes_written);
00316       return TRUE;
00317     }
00318   else if (bytes_written < 0)
00319     {
00320       /* EINTR already handled for us */
00321       
00322       if (_dbus_get_is_errno_eagain_or_ewouldblock ())
00323         ;
00324       else
00325         {
00326           _dbus_verbose ("Error writing to remote app: %s\n",
00327                          _dbus_strerror_from_errno ());
00328           do_io_error (transport);
00329         }
00330     }
00331 
00332   return FALSE;
00333 }
00334 
00335 /* FALSE on OOM */
00336 static dbus_bool_t
00337 exchange_credentials (DBusTransport *transport,
00338                       dbus_bool_t    do_reading,
00339                       dbus_bool_t    do_writing)
00340 {
00341   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
00342   DBusError error = DBUS_ERROR_INIT;
00343 
00344   _dbus_verbose ("exchange_credentials: do_reading = %d, do_writing = %d\n",
00345                   do_reading, do_writing);
00346 
00347   if (do_writing && transport->send_credentials_pending)
00348     {
00349       if (_dbus_send_credentials_socket (socket_transport->fd,
00350                                          &error))
00351         {
00352           transport->send_credentials_pending = FALSE;
00353         }
00354       else
00355         {
00356           _dbus_verbose ("Failed to write credentials: %s\n", error.message);
00357           dbus_error_free (&error);
00358           do_io_error (transport);
00359         }
00360     }
00361   
00362   if (do_reading && transport->receive_credentials_pending)
00363     {
00364       /* FIXME this can fail due to IO error _or_ OOM, broken
00365        * (somewhat tricky to fix since the OOM error can be set after
00366        * we already read the credentials byte, so basically we need to
00367        * separate reading the byte and storing it in the
00368        * transport->credentials). Does not really matter for now
00369        * because storing in credentials never actually fails on unix.
00370        */      
00371       if (_dbus_read_credentials_socket (socket_transport->fd,
00372                                          transport->credentials,
00373                                          &error))
00374         {
00375           transport->receive_credentials_pending = FALSE;
00376         }
00377       else
00378         {
00379           _dbus_verbose ("Failed to read credentials %s\n", error.message);
00380           dbus_error_free (&error);
00381           do_io_error (transport);
00382         }
00383     }
00384 
00385   if (!(transport->send_credentials_pending ||
00386         transport->receive_credentials_pending))
00387     {
00388       if (!_dbus_auth_set_credentials (transport->auth,
00389                                        transport->credentials))
00390         return FALSE;
00391     }
00392 
00393   return TRUE;
00394 }
00395 
00396 static dbus_bool_t
00397 do_authentication (DBusTransport *transport,
00398                    dbus_bool_t    do_reading,
00399                    dbus_bool_t    do_writing,
00400                    dbus_bool_t   *auth_completed)
00401 {
00402   dbus_bool_t oom;
00403   dbus_bool_t orig_auth_state;
00404 
00405   oom = FALSE;
00406   
00407   orig_auth_state = _dbus_transport_get_is_authenticated (transport);
00408 
00409   /* This is essential to avoid the check_write_watch() at the end,
00410    * we don't want to add a write watch in do_iteration before
00411    * we try writing and get EAGAIN
00412    */
00413   if (orig_auth_state)
00414     {
00415       if (auth_completed)
00416         *auth_completed = FALSE;
00417       return TRUE;
00418     }
00419   
00420   _dbus_transport_ref (transport);
00421   
00422   while (!_dbus_transport_get_is_authenticated (transport) &&
00423          _dbus_transport_get_is_connected (transport))
00424     {      
00425       if (!exchange_credentials (transport, do_reading, do_writing))
00426         {
00427           /* OOM */
00428           oom = TRUE;
00429           goto out;
00430         }
00431       
00432       if (transport->send_credentials_pending ||
00433           transport->receive_credentials_pending)
00434         {
00435           _dbus_verbose ("send_credentials_pending = %d receive_credentials_pending = %d\n",
00436                          transport->send_credentials_pending,
00437                          transport->receive_credentials_pending);
00438           goto out;
00439         }
00440 
00441 #define TRANSPORT_SIDE(t) ((t)->is_server ? "server" : "client")
00442       switch (_dbus_auth_do_work (transport->auth))
00443         {
00444         case DBUS_AUTH_STATE_WAITING_FOR_INPUT:
00445           _dbus_verbose (" %s auth state: waiting for input\n",
00446                          TRANSPORT_SIDE (transport));
00447           if (!do_reading || !read_data_into_auth (transport, &oom))
00448             goto out;
00449           break;
00450       
00451         case DBUS_AUTH_STATE_WAITING_FOR_MEMORY:
00452           _dbus_verbose (" %s auth state: waiting for memory\n",
00453                          TRANSPORT_SIDE (transport));
00454           oom = TRUE;
00455           goto out;
00456           break;
00457       
00458         case DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND:
00459           _dbus_verbose (" %s auth state: bytes to send\n",
00460                          TRANSPORT_SIDE (transport));
00461           if (!do_writing || !write_data_from_auth (transport))
00462             goto out;
00463           break;
00464       
00465         case DBUS_AUTH_STATE_NEED_DISCONNECT:
00466           _dbus_verbose (" %s auth state: need to disconnect\n",
00467                          TRANSPORT_SIDE (transport));
00468           do_io_error (transport);
00469           break;
00470       
00471         case DBUS_AUTH_STATE_AUTHENTICATED:
00472           _dbus_verbose (" %s auth state: authenticated\n",
00473                          TRANSPORT_SIDE (transport));
00474           break;
00475         }
00476     }
00477 
00478  out:
00479   if (auth_completed)
00480     *auth_completed = (orig_auth_state != _dbus_transport_get_is_authenticated (transport));
00481   
00482   check_read_watch (transport);
00483   check_write_watch (transport);
00484   _dbus_transport_unref (transport);
00485 
00486   if (oom)
00487     return FALSE;
00488   else
00489     return TRUE;
00490 }
00491 
00492 /* returns false on oom */
00493 static dbus_bool_t
00494 do_writing (DBusTransport *transport)
00495 {
00496   int total;
00497   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
00498   dbus_bool_t oom;
00499   
00500   /* No messages without authentication! */
00501   if (!_dbus_transport_get_is_authenticated (transport))
00502     {
00503       _dbus_verbose ("Not authenticated, not writing anything\n");
00504       return TRUE;
00505     }
00506 
00507   if (transport->disconnected)
00508     {
00509       _dbus_verbose ("Not connected, not writing anything\n");
00510       return TRUE;
00511     }
00512 
00513 #if 1
00514   _dbus_verbose ("do_writing(), have_messages = %d, fd = %d\n",
00515                  _dbus_connection_has_messages_to_send_unlocked (transport->connection),
00516                  socket_transport->fd);
00517 #endif
00518   
00519   oom = FALSE;
00520   total = 0;
00521 
00522   while (!transport->disconnected &&
00523          _dbus_connection_has_messages_to_send_unlocked (transport->connection))
00524     {
00525       int bytes_written;
00526       DBusMessage *message;
00527       const DBusString *header;
00528       const DBusString *body;
00529       int header_len, body_len;
00530       int total_bytes_to_write;
00531       
00532       if (total > socket_transport->max_bytes_written_per_iteration)
00533         {
00534           _dbus_verbose ("%d bytes exceeds %d bytes written per iteration, returning\n",
00535                          total, socket_transport->max_bytes_written_per_iteration);
00536           goto out;
00537         }
00538       
00539       message = _dbus_connection_get_message_to_send (transport->connection);
00540       _dbus_assert (message != NULL);
00541       dbus_message_lock (message);
00542 
00543 #if 0
00544       _dbus_verbose ("writing message %p\n", message);
00545 #endif
00546       
00547       _dbus_message_get_network_data (message,
00548                                       &header, &body);
00549 
00550       header_len = _dbus_string_get_length (header);
00551       body_len = _dbus_string_get_length (body);
00552 
00553       if (_dbus_auth_needs_encoding (transport->auth))
00554         {
00555           /* Does fd passing even make sense with encoded data? */
00556           _dbus_assert(!DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport));
00557 
00558           if (_dbus_string_get_length (&socket_transport->encoded_outgoing) == 0)
00559             {
00560               if (!_dbus_auth_encode_data (transport->auth,
00561                                            header, &socket_transport->encoded_outgoing))
00562                 {
00563                   oom = TRUE;
00564                   goto out;
00565                 }
00566               
00567               if (!_dbus_auth_encode_data (transport->auth,
00568                                            body, &socket_transport->encoded_outgoing))
00569                 {
00570                   _dbus_string_set_length (&socket_transport->encoded_outgoing, 0);
00571                   oom = TRUE;
00572                   goto out;
00573                 }
00574             }
00575           
00576           total_bytes_to_write = _dbus_string_get_length (&socket_transport->encoded_outgoing);
00577 
00578 #if 0
00579           _dbus_verbose ("encoded message is %d bytes\n",
00580                          total_bytes_to_write);
00581 #endif
00582           
00583           bytes_written =
00584             _dbus_write_socket (socket_transport->fd,
00585                                 &socket_transport->encoded_outgoing,
00586                                 socket_transport->message_bytes_written,
00587                                 total_bytes_to_write - socket_transport->message_bytes_written);
00588         }
00589       else
00590         {
00591           total_bytes_to_write = header_len + body_len;
00592 
00593 #if 0
00594           _dbus_verbose ("message is %d bytes\n",
00595                          total_bytes_to_write);
00596 #endif
00597 
00598 #ifdef HAVE_UNIX_FD_PASSING
00599           if (socket_transport->message_bytes_written <= 0 && DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport))
00600             {
00601               /* Send the fds along with the first byte of the message */
00602               const int *unix_fds;
00603               unsigned n;
00604 
00605               _dbus_message_get_unix_fds(message, &unix_fds, &n);
00606 
00607               bytes_written =
00608                 _dbus_write_socket_with_unix_fds_two (socket_transport->fd,
00609                                                       header,
00610                                                       socket_transport->message_bytes_written,
00611                                                       header_len - socket_transport->message_bytes_written,
00612                                                       body,
00613                                                       0, body_len,
00614                                                       unix_fds,
00615                                                       n);
00616 
00617               if (bytes_written > 0 && n > 0)
00618                 _dbus_verbose("Wrote %i unix fds\n", n);
00619             }
00620           else
00621 #endif
00622             {
00623               if (socket_transport->message_bytes_written < header_len)
00624                 {
00625                   bytes_written =
00626                     _dbus_write_socket_two (socket_transport->fd,
00627                                             header,
00628                                             socket_transport->message_bytes_written,
00629                                             header_len - socket_transport->message_bytes_written,
00630                                             body,
00631                                             0, body_len);
00632                 }
00633               else
00634                 {
00635                   bytes_written =
00636                     _dbus_write_socket (socket_transport->fd,
00637                                         body,
00638                                         (socket_transport->message_bytes_written - header_len),
00639                                         body_len -
00640                                         (socket_transport->message_bytes_written - header_len));
00641                 }
00642             }
00643         }
00644 
00645       if (bytes_written < 0)
00646         {
00647           /* EINTR already handled for us */
00648           
00649           /* If the other end closed the socket with close() or shutdown(), we
00650            * receive EPIPE here but we must not close the socket yet: there
00651            * might still be some data to read. See:
00652            * http://lists.freedesktop.org/archives/dbus/2008-March/009526.html
00653            */
00654           
00655           if (_dbus_get_is_errno_eagain_or_ewouldblock () || _dbus_get_is_errno_epipe ())
00656             goto out;
00657 
00658           /* Since Linux commit 25888e (from 2.6.37-rc4, Nov 2010), sendmsg()
00659            * on Unix sockets returns -1 errno=ETOOMANYREFS when the passfd
00660            * mechanism (SCM_RIGHTS) is used recursively with a recursion level
00661            * of maximum 4. The kernel does not have an API to check whether
00662            * the passed fds can be forwarded and it can change asynchronously.
00663            * See:
00664            * https://bugs.freedesktop.org/show_bug.cgi?id=80163
00665            */
00666 
00667           else if (_dbus_get_is_errno_etoomanyrefs ())
00668             {
00669               /* We only send fds in the first byte of the message.
00670                * ETOOMANYREFS cannot happen after.
00671                */
00672               _dbus_assert (socket_transport->message_bytes_written == 0);
00673 
00674               _dbus_verbose (" discard message of %d bytes due to ETOOMANYREFS\n",
00675                              total_bytes_to_write);
00676 
00677               socket_transport->message_bytes_written = 0;
00678               _dbus_string_set_length (&socket_transport->encoded_outgoing, 0);
00679               _dbus_string_compact (&socket_transport->encoded_outgoing, 2048);
00680 
00681               /* The message was not actually sent but it needs to be removed
00682                * from the outgoing queue
00683                */
00684               _dbus_connection_message_sent (transport->connection,
00685                                              message);
00686             }
00687           else
00688             {
00689               _dbus_verbose ("Error writing to remote app: %s\n",
00690                              _dbus_strerror_from_errno ());
00691               do_io_error (transport);
00692               goto out;
00693             }
00694         }
00695       else
00696         {
00697           _dbus_verbose (" wrote %d bytes of %d\n", bytes_written,
00698                          total_bytes_to_write);
00699           
00700           total += bytes_written;
00701           socket_transport->message_bytes_written += bytes_written;
00702 
00703           _dbus_assert (socket_transport->message_bytes_written <=
00704                         total_bytes_to_write);
00705           
00706           if (socket_transport->message_bytes_written == total_bytes_to_write)
00707             {
00708               socket_transport->message_bytes_written = 0;
00709               _dbus_string_set_length (&socket_transport->encoded_outgoing, 0);
00710               _dbus_string_compact (&socket_transport->encoded_outgoing, 2048);
00711 
00712               _dbus_connection_message_sent (transport->connection,
00713                                              message);
00714             }
00715         }
00716     }
00717 
00718  out:
00719   if (oom)
00720     return FALSE;
00721   else
00722     return TRUE;
00723 }
00724 
00725 /* returns false on out-of-memory */
00726 static dbus_bool_t
00727 do_reading (DBusTransport *transport)
00728 {
00729   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
00730   DBusString *buffer;
00731   int bytes_read;
00732   int total;
00733   dbus_bool_t oom;
00734 
00735   _dbus_verbose ("fd = %d\n",socket_transport->fd);
00736   
00737   /* No messages without authentication! */
00738   if (!_dbus_transport_get_is_authenticated (transport))
00739     return TRUE;
00740 
00741   oom = FALSE;
00742   
00743   total = 0;
00744 
00745  again:
00746   
00747   /* See if we've exceeded max messages and need to disable reading */
00748   check_read_watch (transport);
00749   
00750   if (total > socket_transport->max_bytes_read_per_iteration)
00751     {
00752       _dbus_verbose ("%d bytes exceeds %d bytes read per iteration, returning\n",
00753                      total, socket_transport->max_bytes_read_per_iteration);
00754       goto out;
00755     }
00756 
00757   _dbus_assert (socket_transport->read_watch != NULL ||
00758                 transport->disconnected);
00759   
00760   if (transport->disconnected)
00761     goto out;
00762 
00763   if (!dbus_watch_get_enabled (socket_transport->read_watch))
00764     return TRUE;
00765   
00766   if (_dbus_auth_needs_decoding (transport->auth))
00767     {
00768       /* Does fd passing even make sense with encoded data? */
00769       _dbus_assert(!DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport));
00770 
00771       if (_dbus_string_get_length (&socket_transport->encoded_incoming) > 0)
00772         bytes_read = _dbus_string_get_length (&socket_transport->encoded_incoming);
00773       else
00774         bytes_read = _dbus_read_socket (socket_transport->fd,
00775                                         &socket_transport->encoded_incoming,
00776                                         socket_transport->max_bytes_read_per_iteration);
00777 
00778       _dbus_assert (_dbus_string_get_length (&socket_transport->encoded_incoming) ==
00779                     bytes_read);
00780       
00781       if (bytes_read > 0)
00782         {
00783           int orig_len;
00784           
00785           _dbus_message_loader_get_buffer (transport->loader,
00786                                            &buffer);
00787 
00788           orig_len = _dbus_string_get_length (buffer);
00789           
00790           if (!_dbus_auth_decode_data (transport->auth,
00791                                        &socket_transport->encoded_incoming,
00792                                        buffer))
00793             {
00794               _dbus_verbose ("Out of memory decoding incoming data\n");
00795               _dbus_message_loader_return_buffer (transport->loader,
00796                                               buffer,
00797                                               _dbus_string_get_length (buffer) - orig_len);
00798 
00799               oom = TRUE;
00800               goto out;
00801             }
00802 
00803           _dbus_message_loader_return_buffer (transport->loader,
00804                                               buffer,
00805                                               _dbus_string_get_length (buffer) - orig_len);
00806 
00807           _dbus_string_set_length (&socket_transport->encoded_incoming, 0);
00808           _dbus_string_compact (&socket_transport->encoded_incoming, 2048);
00809         }
00810     }
00811   else
00812     {
00813       _dbus_message_loader_get_buffer (transport->loader,
00814                                        &buffer);
00815 
00816 #ifdef HAVE_UNIX_FD_PASSING
00817       if (DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport))
00818         {
00819           int *fds, n_fds;
00820 
00821           if (!_dbus_message_loader_get_unix_fds(transport->loader, &fds, &n_fds))
00822             {
00823               _dbus_verbose ("Out of memory reading file descriptors\n");
00824               _dbus_message_loader_return_buffer (transport->loader, buffer, 0);
00825               oom = TRUE;
00826               goto out;
00827             }
00828 
00829           bytes_read = _dbus_read_socket_with_unix_fds(socket_transport->fd,
00830                                                        buffer,
00831                                                        socket_transport->max_bytes_read_per_iteration,
00832                                                        fds, &n_fds);
00833 
00834           if (bytes_read >= 0 && n_fds > 0)
00835             _dbus_verbose("Read %i unix fds\n", n_fds);
00836 
00837           _dbus_message_loader_return_unix_fds(transport->loader, fds, bytes_read < 0 ? 0 : n_fds);
00838         }
00839       else
00840 #endif
00841         {
00842           bytes_read = _dbus_read_socket (socket_transport->fd,
00843                                           buffer, socket_transport->max_bytes_read_per_iteration);
00844         }
00845 
00846       _dbus_message_loader_return_buffer (transport->loader,
00847                                           buffer,
00848                                           bytes_read < 0 ? 0 : bytes_read);
00849     }
00850   
00851   if (bytes_read < 0)
00852     {
00853       /* EINTR already handled for us */
00854 
00855       if (_dbus_get_is_errno_enomem ())
00856         {
00857           _dbus_verbose ("Out of memory in read()/do_reading()\n");
00858           oom = TRUE;
00859           goto out;
00860         }
00861       else if (_dbus_get_is_errno_eagain_or_ewouldblock ())
00862         goto out;
00863       else
00864         {
00865           _dbus_verbose ("Error reading from remote app: %s\n",
00866                          _dbus_strerror_from_errno ());
00867           do_io_error (transport);
00868           goto out;
00869         }
00870     }
00871   else if (bytes_read == 0)
00872     {
00873       _dbus_verbose ("Disconnected from remote app\n");
00874       do_io_error (transport);
00875       goto out;
00876     }
00877   else
00878     {
00879       _dbus_verbose (" read %d bytes\n", bytes_read);
00880       
00881       total += bytes_read;      
00882 
00883       if (!_dbus_transport_queue_messages (transport))
00884         {
00885           oom = TRUE;
00886           _dbus_verbose (" out of memory when queueing messages we just read in the transport\n");
00887           goto out;
00888         }
00889       
00890       /* Try reading more data until we get EAGAIN and return, or
00891        * exceed max bytes per iteration.  If in blocking mode of
00892        * course we'll block instead of returning.
00893        */
00894       goto again;
00895     }
00896 
00897  out:
00898   if (oom)
00899     return FALSE;
00900   else
00901     return TRUE;
00902 }
00903 
00904 static dbus_bool_t
00905 unix_error_with_read_to_come (DBusTransport *itransport,
00906                               DBusWatch     *watch,
00907                               unsigned int   flags)
00908 {
00909   DBusTransportSocket *transport = (DBusTransportSocket *) itransport;
00910 
00911   if (!(flags & DBUS_WATCH_HANGUP || flags & DBUS_WATCH_ERROR))
00912     return FALSE;
00913    
00914   /* If we have a read watch enabled ...
00915      we -might have data incoming ... => handle the HANGUP there */
00916   if (watch != transport->read_watch &&
00917       _dbus_watch_get_enabled (transport->read_watch))
00918     return FALSE;
00919       
00920   return TRUE; 
00921 }
00922 
00923 static dbus_bool_t
00924 socket_handle_watch (DBusTransport *transport,
00925                    DBusWatch     *watch,
00926                    unsigned int   flags)
00927 {
00928   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
00929 
00930   _dbus_assert (watch == socket_transport->read_watch ||
00931                 watch == socket_transport->write_watch);
00932   _dbus_assert (watch != NULL);
00933   
00934   /* If we hit an error here on a write watch, don't disconnect the transport yet because data can
00935    * still be in the buffer and do_reading may need several iteration to read
00936    * it all (because of its max_bytes_read_per_iteration limit). 
00937    */
00938   if (!(flags & DBUS_WATCH_READABLE) && unix_error_with_read_to_come (transport, watch, flags))
00939     {
00940       _dbus_verbose ("Hang up or error on watch\n");
00941       _dbus_transport_disconnect (transport);
00942       return TRUE;
00943     }
00944   
00945   if (watch == socket_transport->read_watch &&
00946       (flags & DBUS_WATCH_READABLE))
00947     {
00948       dbus_bool_t auth_finished;
00949 #if 1
00950       _dbus_verbose ("handling read watch %p flags = %x\n",
00951                      watch, flags);
00952 #endif
00953       if (!do_authentication (transport, TRUE, FALSE, &auth_finished))
00954         return FALSE;
00955 
00956       /* We don't want to do a read immediately following
00957        * a successful authentication.  This is so we
00958        * have a chance to propagate the authentication
00959        * state further up.  Specifically, we need to
00960        * process any pending data from the auth object.
00961        */
00962       if (!auth_finished)
00963         {
00964           if (!do_reading (transport))
00965             {
00966               _dbus_verbose ("no memory to read\n");
00967               return FALSE;
00968             }
00969         }
00970       else
00971         {
00972           _dbus_verbose ("Not reading anything since we just completed the authentication\n");
00973         }
00974     }
00975   else if (watch == socket_transport->write_watch &&
00976            (flags & DBUS_WATCH_WRITABLE))
00977     {
00978 #if 1
00979       _dbus_verbose ("handling write watch, have_outgoing_messages = %d\n",
00980                      _dbus_connection_has_messages_to_send_unlocked (transport->connection));
00981 #endif
00982       if (!do_authentication (transport, FALSE, TRUE, NULL))
00983         return FALSE;
00984       
00985       if (!do_writing (transport))
00986         {
00987           _dbus_verbose ("no memory to write\n");
00988           return FALSE;
00989         }
00990 
00991       /* See if we still need the write watch */
00992       check_write_watch (transport);
00993     }
00994 #ifdef DBUS_ENABLE_VERBOSE_MODE
00995   else
00996     {
00997       if (watch == socket_transport->read_watch)
00998         _dbus_verbose ("asked to handle read watch with non-read condition 0x%x\n",
00999                        flags);
01000       else if (watch == socket_transport->write_watch)
01001         _dbus_verbose ("asked to handle write watch with non-write condition 0x%x\n",
01002                        flags);
01003       else
01004         _dbus_verbose ("asked to handle watch %p on fd %d that we don't recognize\n",
01005                        watch, dbus_watch_get_socket (watch));
01006     }
01007 #endif /* DBUS_ENABLE_VERBOSE_MODE */
01008 
01009   return TRUE;
01010 }
01011 
01012 static void
01013 socket_disconnect (DBusTransport *transport)
01014 {
01015   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
01016 
01017   _dbus_verbose ("\n");
01018   
01019   free_watches (transport);
01020   
01021   _dbus_close_socket (socket_transport->fd, NULL);
01022   socket_transport->fd = -1;
01023 }
01024 
01025 static dbus_bool_t
01026 socket_connection_set (DBusTransport *transport)
01027 {
01028   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
01029 
01030   _dbus_watch_set_handler (socket_transport->write_watch,
01031                            _dbus_connection_handle_watch,
01032                            transport->connection, NULL);
01033 
01034   _dbus_watch_set_handler (socket_transport->read_watch,
01035                            _dbus_connection_handle_watch,
01036                            transport->connection, NULL);
01037   
01038   if (!_dbus_connection_add_watch_unlocked (transport->connection,
01039                                             socket_transport->write_watch))
01040     return FALSE;
01041 
01042   if (!_dbus_connection_add_watch_unlocked (transport->connection,
01043                                             socket_transport->read_watch))
01044     {
01045       _dbus_connection_remove_watch_unlocked (transport->connection,
01046                                               socket_transport->write_watch);
01047       return FALSE;
01048     }
01049 
01050   check_read_watch (transport);
01051   check_write_watch (transport);
01052 
01053   return TRUE;
01054 }
01055 
01063 static  void
01064 socket_do_iteration (DBusTransport *transport,
01065                    unsigned int   flags,
01066                    int            timeout_milliseconds)
01067 {
01068   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
01069   DBusPollFD poll_fd;
01070   int poll_res;
01071   int poll_timeout;
01072 
01073   _dbus_verbose (" iteration flags = %s%s timeout = %d read_watch = %p write_watch = %p fd = %d\n",
01074                  flags & DBUS_ITERATION_DO_READING ? "read" : "",
01075                  flags & DBUS_ITERATION_DO_WRITING ? "write" : "",
01076                  timeout_milliseconds,
01077                  socket_transport->read_watch,
01078                  socket_transport->write_watch,
01079                  socket_transport->fd);
01080   
01081   /* the passed in DO_READING/DO_WRITING flags indicate whether to
01082    * read/write messages, but regardless of those we may need to block
01083    * for reading/writing to do auth.  But if we do reading for auth,
01084    * we don't want to read any messages yet if not given DO_READING.
01085    */
01086 
01087   poll_fd.fd = socket_transport->fd;
01088   poll_fd.events = 0;
01089   
01090   if (_dbus_transport_get_is_authenticated (transport))
01091     {
01092       /* This is kind of a hack; if we have stuff to write, then try
01093        * to avoid the poll. This is probably about a 5% speedup on an
01094        * echo client/server.
01095        *
01096        * If both reading and writing were requested, we want to avoid this
01097        * since it could have funky effects:
01098        *   - both ends spinning waiting for the other one to read
01099        *     data so they can finish writing
01100        *   - prioritizing all writing ahead of reading
01101        */
01102       if ((flags & DBUS_ITERATION_DO_WRITING) &&
01103           !(flags & (DBUS_ITERATION_DO_READING | DBUS_ITERATION_BLOCK)) &&
01104           !transport->disconnected &&
01105           _dbus_connection_has_messages_to_send_unlocked (transport->connection))
01106         {
01107           do_writing (transport);
01108 
01109           if (transport->disconnected ||
01110               !_dbus_connection_has_messages_to_send_unlocked (transport->connection))
01111             goto out;
01112         }
01113 
01114       /* If we get here, we decided to do the poll() after all */
01115       _dbus_assert (socket_transport->read_watch);
01116       if (flags & DBUS_ITERATION_DO_READING)
01117         poll_fd.events |= _DBUS_POLLIN;
01118 
01119       _dbus_assert (socket_transport->write_watch);
01120       if (flags & DBUS_ITERATION_DO_WRITING)
01121         poll_fd.events |= _DBUS_POLLOUT;
01122     }
01123   else
01124     {
01125       DBusAuthState auth_state;
01126       
01127       auth_state = _dbus_auth_do_work (transport->auth);
01128 
01129       if (transport->receive_credentials_pending ||
01130           auth_state == DBUS_AUTH_STATE_WAITING_FOR_INPUT)
01131         poll_fd.events |= _DBUS_POLLIN;
01132 
01133       if (transport->send_credentials_pending ||
01134           auth_state == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND)
01135         poll_fd.events |= _DBUS_POLLOUT;
01136     }
01137 
01138   if (poll_fd.events)
01139     {
01140       if (flags & DBUS_ITERATION_BLOCK)
01141         poll_timeout = timeout_milliseconds;
01142       else
01143         poll_timeout = 0;
01144 
01145       /* For blocking selects we drop the connection lock here
01146        * to avoid blocking out connection access during a potentially
01147        * indefinite blocking call. The io path is still protected
01148        * by the io_path_cond condvar, so we won't reenter this.
01149        */
01150       if (flags & DBUS_ITERATION_BLOCK)
01151         {
01152           _dbus_verbose ("unlock pre poll\n");
01153           _dbus_connection_unlock (transport->connection);
01154         }
01155       
01156     again:
01157       poll_res = _dbus_poll (&poll_fd, 1, poll_timeout);
01158 
01159       if (poll_res < 0 && _dbus_get_is_errno_eintr ())
01160         goto again;
01161 
01162       if (flags & DBUS_ITERATION_BLOCK)
01163         {
01164           _dbus_verbose ("lock post poll\n");
01165           _dbus_connection_lock (transport->connection);
01166         }
01167       
01168       if (poll_res >= 0)
01169         {
01170           if (poll_res == 0)
01171             poll_fd.revents = 0; /* some concern that posix does not guarantee this;
01172                                   * valgrind flags it as an error. though it probably
01173                                   * is guaranteed on linux at least.
01174                                   */
01175           
01176           if (poll_fd.revents & _DBUS_POLLERR)
01177             do_io_error (transport);
01178           else
01179             {
01180               dbus_bool_t need_read = (poll_fd.revents & _DBUS_POLLIN) > 0;
01181               dbus_bool_t need_write = (poll_fd.revents & _DBUS_POLLOUT) > 0;
01182               dbus_bool_t authentication_completed;
01183 
01184               _dbus_verbose ("in iteration, need_read=%d need_write=%d\n",
01185                              need_read, need_write);
01186               do_authentication (transport, need_read, need_write,
01187                                  &authentication_completed);
01188 
01189               /* See comment in socket_handle_watch. */
01190               if (authentication_completed)
01191                 goto out;
01192                                  
01193               if (need_read && (flags & DBUS_ITERATION_DO_READING))
01194                 do_reading (transport);
01195               if (need_write && (flags & DBUS_ITERATION_DO_WRITING))
01196                 do_writing (transport);
01197             }
01198         }
01199       else
01200         {
01201           _dbus_verbose ("Error from _dbus_poll(): %s\n",
01202                          _dbus_strerror_from_errno ());
01203         }
01204     }
01205 
01206 
01207  out:
01208   /* We need to install the write watch only if we did not
01209    * successfully write everything. Note we need to be careful that we
01210    * don't call check_write_watch *before* do_writing, since it's
01211    * inefficient to add the write watch, and we can avoid it most of
01212    * the time since we can write immediately.
01213    * 
01214    * However, we MUST always call check_write_watch(); DBusConnection code
01215    * relies on the fact that running an iteration will notice that
01216    * messages are pending.
01217    */
01218   check_write_watch (transport);
01219 
01220   _dbus_verbose (" ... leaving do_iteration()\n");
01221 }
01222 
01223 static void
01224 socket_live_messages_changed (DBusTransport *transport)
01225 {
01226   /* See if we should look for incoming messages again */
01227   check_read_watch (transport);
01228 }
01229 
01230 
01231 static dbus_bool_t
01232 socket_get_socket_fd (DBusTransport *transport,
01233                       int           *fd_p)
01234 {
01235   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
01236   
01237   *fd_p = socket_transport->fd;
01238   
01239   return TRUE;
01240 }
01241 
01242 static const DBusTransportVTable socket_vtable = {
01243   socket_finalize,
01244   socket_handle_watch,
01245   socket_disconnect,
01246   socket_connection_set,
01247   socket_do_iteration,
01248   socket_live_messages_changed,
01249   socket_get_socket_fd
01250 };
01251 
01263 DBusTransport*
01264 _dbus_transport_new_for_socket (int               fd,
01265                                 const DBusString *server_guid,
01266                                 const DBusString *address)
01267 {
01268   DBusTransportSocket *socket_transport;
01269   
01270   socket_transport = dbus_new0 (DBusTransportSocket, 1);
01271   if (socket_transport == NULL)
01272     return NULL;
01273 
01274   if (!_dbus_string_init (&socket_transport->encoded_outgoing))
01275     goto failed_0;
01276 
01277   if (!_dbus_string_init (&socket_transport->encoded_incoming))
01278     goto failed_1;
01279   
01280   socket_transport->write_watch = _dbus_watch_new (fd,
01281                                                  DBUS_WATCH_WRITABLE,
01282                                                  FALSE,
01283                                                  NULL, NULL, NULL);
01284   if (socket_transport->write_watch == NULL)
01285     goto failed_2;
01286   
01287   socket_transport->read_watch = _dbus_watch_new (fd,
01288                                                 DBUS_WATCH_READABLE,
01289                                                 FALSE,
01290                                                 NULL, NULL, NULL);
01291   if (socket_transport->read_watch == NULL)
01292     goto failed_3;
01293 
01294   if (!_dbus_transport_init_base (&socket_transport->base,
01295                                   &socket_vtable,
01296                                   server_guid, address))
01297     goto failed_4;
01298 
01299 #ifdef HAVE_UNIX_FD_PASSING
01300   _dbus_auth_set_unix_fd_possible(socket_transport->base.auth, _dbus_socket_can_pass_unix_fd(fd));
01301 #endif
01302 
01303   socket_transport->fd = fd;
01304   socket_transport->message_bytes_written = 0;
01305   
01306   /* These values should probably be tunable or something. */     
01307   socket_transport->max_bytes_read_per_iteration = 2048;
01308   socket_transport->max_bytes_written_per_iteration = 2048;
01309   
01310   return (DBusTransport*) socket_transport;
01311 
01312  failed_4:
01313   _dbus_watch_unref (socket_transport->read_watch);
01314  failed_3:
01315   _dbus_watch_unref (socket_transport->write_watch);
01316  failed_2:
01317   _dbus_string_free (&socket_transport->encoded_incoming);
01318  failed_1:
01319   _dbus_string_free (&socket_transport->encoded_outgoing);
01320  failed_0:
01321   dbus_free (socket_transport);
01322   return NULL;
01323 }
01324 
01336 DBusTransport*
01337 _dbus_transport_new_for_tcp_socket (const char     *host,
01338                                     const char     *port,
01339                                     const char     *family,
01340                                     const char     *noncefile,
01341                                     DBusError      *error)
01342 {
01343   int fd;
01344   DBusTransport *transport;
01345   DBusString address;
01346   
01347   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01348 
01349   if (!_dbus_string_init (&address))
01350     {
01351       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01352       return NULL;
01353     }
01354 
01355   if (host == NULL)
01356     host = "localhost";
01357 
01358   if (!_dbus_string_append (&address, noncefile ? "nonce-tcp:" : "tcp:"))
01359     goto error;
01360 
01361   if (!_dbus_string_append (&address, "host=") ||
01362       !_dbus_string_append (&address, host))
01363     goto error;
01364 
01365   if (!_dbus_string_append (&address, ",port=") ||
01366       !_dbus_string_append (&address, port))
01367     goto error;
01368 
01369   if (family != NULL &&
01370       (!_dbus_string_append (&address, "family=") ||
01371        !_dbus_string_append (&address, family)))
01372     goto error;
01373 
01374   if (noncefile != NULL &&
01375       (!_dbus_string_append (&address, "noncefile=") ||
01376        !_dbus_string_append (&address, noncefile)))
01377     goto error;
01378 
01379   fd = _dbus_connect_tcp_socket_with_nonce (host, port, family, noncefile, error);
01380   if (fd < 0)
01381     {
01382       _DBUS_ASSERT_ERROR_IS_SET (error);
01383       _dbus_string_free (&address);
01384       return NULL;
01385     }
01386 
01387   _dbus_verbose ("Successfully connected to tcp socket %s:%s\n",
01388                  host, port);
01389   
01390   transport = _dbus_transport_new_for_socket (fd, NULL, &address);
01391   _dbus_string_free (&address);
01392   if (transport == NULL)
01393     {
01394       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01395       _dbus_close_socket (fd, NULL);
01396       fd = -1;
01397     }
01398 
01399   return transport;
01400 
01401 error:
01402   _dbus_string_free (&address);
01403   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01404   return NULL;
01405 }
01406 
01415 DBusTransportOpenResult
01416 _dbus_transport_open_socket(DBusAddressEntry  *entry,
01417                             DBusTransport    **transport_p,                            
01418                             DBusError         *error)
01419 {
01420   const char *method;
01421   dbus_bool_t isTcp;
01422   dbus_bool_t isNonceTcp;
01423   
01424   method = dbus_address_entry_get_method (entry);
01425   _dbus_assert (method != NULL);
01426 
01427   isTcp = strcmp (method, "tcp") == 0;
01428   isNonceTcp = strcmp (method, "nonce-tcp") == 0;
01429 
01430   if (isTcp || isNonceTcp)
01431     {
01432       const char *host = dbus_address_entry_get_value (entry, "host");
01433       const char *port = dbus_address_entry_get_value (entry, "port");
01434       const char *family = dbus_address_entry_get_value (entry, "family");
01435       const char *noncefile = dbus_address_entry_get_value (entry, "noncefile");
01436 
01437       if ((isNonceTcp == TRUE) != (noncefile != NULL)) {
01438           _dbus_set_bad_address (error, method, "noncefile", NULL);
01439           return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
01440       }
01441 
01442       if (port == NULL)
01443         {
01444           _dbus_set_bad_address (error, method, "port", NULL);
01445           return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
01446         }
01447 
01448       *transport_p = _dbus_transport_new_for_tcp_socket (host, port, family, noncefile, error);
01449       if (*transport_p == NULL)
01450         {
01451           _DBUS_ASSERT_ERROR_IS_SET (error);
01452           return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
01453         }
01454       else
01455         {
01456           _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01457           return DBUS_TRANSPORT_OPEN_OK;
01458         }
01459     }
01460   else
01461     {
01462       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01463       return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
01464     }
01465 }
01466