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