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           /* For some discussion of why we also ignore EPIPE here, see
00650            * http://lists.freedesktop.org/archives/dbus/2008-March/009526.html
00651            */
00652           
00653           if (_dbus_get_is_errno_eagain_or_ewouldblock () || _dbus_get_is_errno_epipe ())
00654             goto out;
00655           else
00656             {
00657               _dbus_verbose ("Error writing to remote app: %s\n",
00658                              _dbus_strerror_from_errno ());
00659               do_io_error (transport);
00660               goto out;
00661             }
00662         }
00663       else
00664         {
00665           _dbus_verbose (" wrote %d bytes of %d\n", bytes_written,
00666                          total_bytes_to_write);
00667           
00668           total += bytes_written;
00669           socket_transport->message_bytes_written += bytes_written;
00670 
00671           _dbus_assert (socket_transport->message_bytes_written <=
00672                         total_bytes_to_write);
00673           
00674           if (socket_transport->message_bytes_written == total_bytes_to_write)
00675             {
00676               socket_transport->message_bytes_written = 0;
00677               _dbus_string_set_length (&socket_transport->encoded_outgoing, 0);
00678               _dbus_string_compact (&socket_transport->encoded_outgoing, 2048);
00679 
00680               _dbus_connection_message_sent (transport->connection,
00681                                              message);
00682             }
00683         }
00684     }
00685 
00686  out:
00687   if (oom)
00688     return FALSE;
00689   else
00690     return TRUE;
00691 }
00692 
00693 /* returns false on out-of-memory */
00694 static dbus_bool_t
00695 do_reading (DBusTransport *transport)
00696 {
00697   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
00698   DBusString *buffer;
00699   int bytes_read;
00700   int total;
00701   dbus_bool_t oom;
00702 
00703   _dbus_verbose ("fd = %d\n",socket_transport->fd);
00704   
00705   /* No messages without authentication! */
00706   if (!_dbus_transport_get_is_authenticated (transport))
00707     return TRUE;
00708 
00709   oom = FALSE;
00710   
00711   total = 0;
00712 
00713  again:
00714   
00715   /* See if we've exceeded max messages and need to disable reading */
00716   check_read_watch (transport);
00717   
00718   if (total > socket_transport->max_bytes_read_per_iteration)
00719     {
00720       _dbus_verbose ("%d bytes exceeds %d bytes read per iteration, returning\n",
00721                      total, socket_transport->max_bytes_read_per_iteration);
00722       goto out;
00723     }
00724 
00725   _dbus_assert (socket_transport->read_watch != NULL ||
00726                 transport->disconnected);
00727   
00728   if (transport->disconnected)
00729     goto out;
00730 
00731   if (!dbus_watch_get_enabled (socket_transport->read_watch))
00732     return TRUE;
00733   
00734   if (_dbus_auth_needs_decoding (transport->auth))
00735     {
00736       /* Does fd passing even make sense with encoded data? */
00737       _dbus_assert(!DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport));
00738 
00739       if (_dbus_string_get_length (&socket_transport->encoded_incoming) > 0)
00740         bytes_read = _dbus_string_get_length (&socket_transport->encoded_incoming);
00741       else
00742         bytes_read = _dbus_read_socket (socket_transport->fd,
00743                                         &socket_transport->encoded_incoming,
00744                                         socket_transport->max_bytes_read_per_iteration);
00745 
00746       _dbus_assert (_dbus_string_get_length (&socket_transport->encoded_incoming) ==
00747                     bytes_read);
00748       
00749       if (bytes_read > 0)
00750         {
00751           int orig_len;
00752           
00753           _dbus_message_loader_get_buffer (transport->loader,
00754                                            &buffer);
00755 
00756           orig_len = _dbus_string_get_length (buffer);
00757           
00758           if (!_dbus_auth_decode_data (transport->auth,
00759                                        &socket_transport->encoded_incoming,
00760                                        buffer))
00761             {
00762               _dbus_verbose ("Out of memory decoding incoming data\n");
00763               _dbus_message_loader_return_buffer (transport->loader,
00764                                               buffer,
00765                                               _dbus_string_get_length (buffer) - orig_len);
00766 
00767               oom = TRUE;
00768               goto out;
00769             }
00770 
00771           _dbus_message_loader_return_buffer (transport->loader,
00772                                               buffer,
00773                                               _dbus_string_get_length (buffer) - orig_len);
00774 
00775           _dbus_string_set_length (&socket_transport->encoded_incoming, 0);
00776           _dbus_string_compact (&socket_transport->encoded_incoming, 2048);
00777         }
00778     }
00779   else
00780     {
00781       _dbus_message_loader_get_buffer (transport->loader,
00782                                        &buffer);
00783 
00784 #ifdef HAVE_UNIX_FD_PASSING
00785       if (DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport))
00786         {
00787           int *fds, n_fds;
00788 
00789           if (!_dbus_message_loader_get_unix_fds(transport->loader, &fds, &n_fds))
00790             {
00791               _dbus_verbose ("Out of memory reading file descriptors\n");
00792               _dbus_message_loader_return_buffer (transport->loader, buffer, 0);
00793               oom = TRUE;
00794               goto out;
00795             }
00796 
00797           bytes_read = _dbus_read_socket_with_unix_fds(socket_transport->fd,
00798                                                        buffer,
00799                                                        socket_transport->max_bytes_read_per_iteration,
00800                                                        fds, &n_fds);
00801 
00802           if (bytes_read >= 0 && n_fds > 0)
00803             _dbus_verbose("Read %i unix fds\n", n_fds);
00804 
00805           _dbus_message_loader_return_unix_fds(transport->loader, fds, bytes_read < 0 ? 0 : n_fds);
00806         }
00807       else
00808 #endif
00809         {
00810           bytes_read = _dbus_read_socket (socket_transport->fd,
00811                                           buffer, socket_transport->max_bytes_read_per_iteration);
00812         }
00813 
00814       _dbus_message_loader_return_buffer (transport->loader,
00815                                           buffer,
00816                                           bytes_read < 0 ? 0 : bytes_read);
00817     }
00818   
00819   if (bytes_read < 0)
00820     {
00821       /* EINTR already handled for us */
00822 
00823       if (_dbus_get_is_errno_enomem ())
00824         {
00825           _dbus_verbose ("Out of memory in read()/do_reading()\n");
00826           oom = TRUE;
00827           goto out;
00828         }
00829       else if (_dbus_get_is_errno_eagain_or_ewouldblock ())
00830         goto out;
00831       else
00832         {
00833           _dbus_verbose ("Error reading from remote app: %s\n",
00834                          _dbus_strerror_from_errno ());
00835           do_io_error (transport);
00836           goto out;
00837         }
00838     }
00839   else if (bytes_read == 0)
00840     {
00841       _dbus_verbose ("Disconnected from remote app\n");
00842       do_io_error (transport);
00843       goto out;
00844     }
00845   else
00846     {
00847       _dbus_verbose (" read %d bytes\n", bytes_read);
00848       
00849       total += bytes_read;      
00850 
00851       if (!_dbus_transport_queue_messages (transport))
00852         {
00853           oom = TRUE;
00854           _dbus_verbose (" out of memory when queueing messages we just read in the transport\n");
00855           goto out;
00856         }
00857       
00858       /* Try reading more data until we get EAGAIN and return, or
00859        * exceed max bytes per iteration.  If in blocking mode of
00860        * course we'll block instead of returning.
00861        */
00862       goto again;
00863     }
00864 
00865  out:
00866   if (oom)
00867     return FALSE;
00868   else
00869     return TRUE;
00870 }
00871 
00872 static dbus_bool_t
00873 unix_error_with_read_to_come (DBusTransport *itransport,
00874                               DBusWatch     *watch,
00875                               unsigned int   flags)
00876 {
00877   DBusTransportSocket *transport = (DBusTransportSocket *) itransport;
00878 
00879   if (!(flags & DBUS_WATCH_HANGUP || flags & DBUS_WATCH_ERROR))
00880     return FALSE;
00881    
00882   /* If we have a read watch enabled ...
00883      we -might have data incoming ... => handle the HANGUP there */
00884   if (watch != transport->read_watch &&
00885       _dbus_watch_get_enabled (transport->read_watch))
00886     return FALSE;
00887       
00888   return TRUE; 
00889 }
00890 
00891 static dbus_bool_t
00892 socket_handle_watch (DBusTransport *transport,
00893                    DBusWatch     *watch,
00894                    unsigned int   flags)
00895 {
00896   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
00897 
00898   _dbus_assert (watch == socket_transport->read_watch ||
00899                 watch == socket_transport->write_watch);
00900   _dbus_assert (watch != NULL);
00901   
00902   /* If we hit an error here on a write watch, don't disconnect the transport yet because data can
00903    * still be in the buffer and do_reading may need several iteration to read
00904    * it all (because of its max_bytes_read_per_iteration limit). 
00905    */
00906   if (!(flags & DBUS_WATCH_READABLE) && unix_error_with_read_to_come (transport, watch, flags))
00907     {
00908       _dbus_verbose ("Hang up or error on watch\n");
00909       _dbus_transport_disconnect (transport);
00910       return TRUE;
00911     }
00912   
00913   if (watch == socket_transport->read_watch &&
00914       (flags & DBUS_WATCH_READABLE))
00915     {
00916       dbus_bool_t auth_finished;
00917 #if 1
00918       _dbus_verbose ("handling read watch %p flags = %x\n",
00919                      watch, flags);
00920 #endif
00921       if (!do_authentication (transport, TRUE, FALSE, &auth_finished))
00922         return FALSE;
00923 
00924       /* We don't want to do a read immediately following
00925        * a successful authentication.  This is so we
00926        * have a chance to propagate the authentication
00927        * state further up.  Specifically, we need to
00928        * process any pending data from the auth object.
00929        */
00930       if (!auth_finished)
00931         {
00932           if (!do_reading (transport))
00933             {
00934               _dbus_verbose ("no memory to read\n");
00935               return FALSE;
00936             }
00937         }
00938       else
00939         {
00940           _dbus_verbose ("Not reading anything since we just completed the authentication\n");
00941         }
00942     }
00943   else if (watch == socket_transport->write_watch &&
00944            (flags & DBUS_WATCH_WRITABLE))
00945     {
00946 #if 1
00947       _dbus_verbose ("handling write watch, have_outgoing_messages = %d\n",
00948                      _dbus_connection_has_messages_to_send_unlocked (transport->connection));
00949 #endif
00950       if (!do_authentication (transport, FALSE, TRUE, NULL))
00951         return FALSE;
00952       
00953       if (!do_writing (transport))
00954         {
00955           _dbus_verbose ("no memory to write\n");
00956           return FALSE;
00957         }
00958 
00959       /* See if we still need the write watch */
00960       check_write_watch (transport);
00961     }
00962 #ifdef DBUS_ENABLE_VERBOSE_MODE
00963   else
00964     {
00965       if (watch == socket_transport->read_watch)
00966         _dbus_verbose ("asked to handle read watch with non-read condition 0x%x\n",
00967                        flags);
00968       else if (watch == socket_transport->write_watch)
00969         _dbus_verbose ("asked to handle write watch with non-write condition 0x%x\n",
00970                        flags);
00971       else
00972         _dbus_verbose ("asked to handle watch %p on fd %d that we don't recognize\n",
00973                        watch, dbus_watch_get_socket (watch));
00974     }
00975 #endif /* DBUS_ENABLE_VERBOSE_MODE */
00976 
00977   return TRUE;
00978 }
00979 
00980 static void
00981 socket_disconnect (DBusTransport *transport)
00982 {
00983   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
00984 
00985   _dbus_verbose ("\n");
00986   
00987   free_watches (transport);
00988   
00989   _dbus_close_socket (socket_transport->fd, NULL);
00990   socket_transport->fd = -1;
00991 }
00992 
00993 static dbus_bool_t
00994 socket_connection_set (DBusTransport *transport)
00995 {
00996   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
00997 
00998   _dbus_watch_set_handler (socket_transport->write_watch,
00999                            _dbus_connection_handle_watch,
01000                            transport->connection, NULL);
01001 
01002   _dbus_watch_set_handler (socket_transport->read_watch,
01003                            _dbus_connection_handle_watch,
01004                            transport->connection, NULL);
01005   
01006   if (!_dbus_connection_add_watch_unlocked (transport->connection,
01007                                             socket_transport->write_watch))
01008     return FALSE;
01009 
01010   if (!_dbus_connection_add_watch_unlocked (transport->connection,
01011                                             socket_transport->read_watch))
01012     {
01013       _dbus_connection_remove_watch_unlocked (transport->connection,
01014                                               socket_transport->write_watch);
01015       return FALSE;
01016     }
01017 
01018   check_read_watch (transport);
01019   check_write_watch (transport);
01020 
01021   return TRUE;
01022 }
01023 
01031 static  void
01032 socket_do_iteration (DBusTransport *transport,
01033                    unsigned int   flags,
01034                    int            timeout_milliseconds)
01035 {
01036   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
01037   DBusPollFD poll_fd;
01038   int poll_res;
01039   int poll_timeout;
01040 
01041   _dbus_verbose (" iteration flags = %s%s timeout = %d read_watch = %p write_watch = %p fd = %d\n",
01042                  flags & DBUS_ITERATION_DO_READING ? "read" : "",
01043                  flags & DBUS_ITERATION_DO_WRITING ? "write" : "",
01044                  timeout_milliseconds,
01045                  socket_transport->read_watch,
01046                  socket_transport->write_watch,
01047                  socket_transport->fd);
01048   
01049   /* the passed in DO_READING/DO_WRITING flags indicate whether to
01050    * read/write messages, but regardless of those we may need to block
01051    * for reading/writing to do auth.  But if we do reading for auth,
01052    * we don't want to read any messages yet if not given DO_READING.
01053    */
01054 
01055   poll_fd.fd = socket_transport->fd;
01056   poll_fd.events = 0;
01057   
01058   if (_dbus_transport_get_is_authenticated (transport))
01059     {
01060       /* This is kind of a hack; if we have stuff to write, then try
01061        * to avoid the poll. This is probably about a 5% speedup on an
01062        * echo client/server.
01063        *
01064        * If both reading and writing were requested, we want to avoid this
01065        * since it could have funky effects:
01066        *   - both ends spinning waiting for the other one to read
01067        *     data so they can finish writing
01068        *   - prioritizing all writing ahead of reading
01069        */
01070       if ((flags & DBUS_ITERATION_DO_WRITING) &&
01071           !(flags & (DBUS_ITERATION_DO_READING | DBUS_ITERATION_BLOCK)) &&
01072           !transport->disconnected &&
01073           _dbus_connection_has_messages_to_send_unlocked (transport->connection))
01074         {
01075           do_writing (transport);
01076 
01077           if (transport->disconnected ||
01078               !_dbus_connection_has_messages_to_send_unlocked (transport->connection))
01079             goto out;
01080         }
01081 
01082       /* If we get here, we decided to do the poll() after all */
01083       _dbus_assert (socket_transport->read_watch);
01084       if (flags & DBUS_ITERATION_DO_READING)
01085         poll_fd.events |= _DBUS_POLLIN;
01086 
01087       _dbus_assert (socket_transport->write_watch);
01088       if (flags & DBUS_ITERATION_DO_WRITING)
01089         poll_fd.events |= _DBUS_POLLOUT;
01090     }
01091   else
01092     {
01093       DBusAuthState auth_state;
01094       
01095       auth_state = _dbus_auth_do_work (transport->auth);
01096 
01097       if (transport->receive_credentials_pending ||
01098           auth_state == DBUS_AUTH_STATE_WAITING_FOR_INPUT)
01099         poll_fd.events |= _DBUS_POLLIN;
01100 
01101       if (transport->send_credentials_pending ||
01102           auth_state == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND)
01103         poll_fd.events |= _DBUS_POLLOUT;
01104     }
01105 
01106   if (poll_fd.events)
01107     {
01108       if (flags & DBUS_ITERATION_BLOCK)
01109         poll_timeout = timeout_milliseconds;
01110       else
01111         poll_timeout = 0;
01112 
01113       /* For blocking selects we drop the connection lock here
01114        * to avoid blocking out connection access during a potentially
01115        * indefinite blocking call. The io path is still protected
01116        * by the io_path_cond condvar, so we won't reenter this.
01117        */
01118       if (flags & DBUS_ITERATION_BLOCK)
01119         {
01120           _dbus_verbose ("unlock pre poll\n");
01121           _dbus_connection_unlock (transport->connection);
01122         }
01123       
01124     again:
01125       poll_res = _dbus_poll (&poll_fd, 1, poll_timeout);
01126 
01127       if (poll_res < 0 && _dbus_get_is_errno_eintr ())
01128         goto again;
01129 
01130       if (flags & DBUS_ITERATION_BLOCK)
01131         {
01132           _dbus_verbose ("lock post poll\n");
01133           _dbus_connection_lock (transport->connection);
01134         }
01135       
01136       if (poll_res >= 0)
01137         {
01138           if (poll_res == 0)
01139             poll_fd.revents = 0; /* some concern that posix does not guarantee this;
01140                                   * valgrind flags it as an error. though it probably
01141                                   * is guaranteed on linux at least.
01142                                   */
01143           
01144           if (poll_fd.revents & _DBUS_POLLERR)
01145             do_io_error (transport);
01146           else
01147             {
01148               dbus_bool_t need_read = (poll_fd.revents & _DBUS_POLLIN) > 0;
01149               dbus_bool_t need_write = (poll_fd.revents & _DBUS_POLLOUT) > 0;
01150               dbus_bool_t authentication_completed;
01151 
01152               _dbus_verbose ("in iteration, need_read=%d need_write=%d\n",
01153                              need_read, need_write);
01154               do_authentication (transport, need_read, need_write,
01155                                  &authentication_completed);
01156 
01157               /* See comment in socket_handle_watch. */
01158               if (authentication_completed)
01159                 goto out;
01160                                  
01161               if (need_read && (flags & DBUS_ITERATION_DO_READING))
01162                 do_reading (transport);
01163               if (need_write && (flags & DBUS_ITERATION_DO_WRITING))
01164                 do_writing (transport);
01165             }
01166         }
01167       else
01168         {
01169           _dbus_verbose ("Error from _dbus_poll(): %s\n",
01170                          _dbus_strerror_from_errno ());
01171         }
01172     }
01173 
01174 
01175  out:
01176   /* We need to install the write watch only if we did not
01177    * successfully write everything. Note we need to be careful that we
01178    * don't call check_write_watch *before* do_writing, since it's
01179    * inefficient to add the write watch, and we can avoid it most of
01180    * the time since we can write immediately.
01181    * 
01182    * However, we MUST always call check_write_watch(); DBusConnection code
01183    * relies on the fact that running an iteration will notice that
01184    * messages are pending.
01185    */
01186   check_write_watch (transport);
01187 
01188   _dbus_verbose (" ... leaving do_iteration()\n");
01189 }
01190 
01191 static void
01192 socket_live_messages_changed (DBusTransport *transport)
01193 {
01194   /* See if we should look for incoming messages again */
01195   check_read_watch (transport);
01196 }
01197 
01198 
01199 static dbus_bool_t
01200 socket_get_socket_fd (DBusTransport *transport,
01201                       int           *fd_p)
01202 {
01203   DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
01204   
01205   *fd_p = socket_transport->fd;
01206   
01207   return TRUE;
01208 }
01209 
01210 static const DBusTransportVTable socket_vtable = {
01211   socket_finalize,
01212   socket_handle_watch,
01213   socket_disconnect,
01214   socket_connection_set,
01215   socket_do_iteration,
01216   socket_live_messages_changed,
01217   socket_get_socket_fd
01218 };
01219 
01231 DBusTransport*
01232 _dbus_transport_new_for_socket (int               fd,
01233                                 const DBusString *server_guid,
01234                                 const DBusString *address)
01235 {
01236   DBusTransportSocket *socket_transport;
01237   
01238   socket_transport = dbus_new0 (DBusTransportSocket, 1);
01239   if (socket_transport == NULL)
01240     return NULL;
01241 
01242   if (!_dbus_string_init (&socket_transport->encoded_outgoing))
01243     goto failed_0;
01244 
01245   if (!_dbus_string_init (&socket_transport->encoded_incoming))
01246     goto failed_1;
01247   
01248   socket_transport->write_watch = _dbus_watch_new (fd,
01249                                                  DBUS_WATCH_WRITABLE,
01250                                                  FALSE,
01251                                                  NULL, NULL, NULL);
01252   if (socket_transport->write_watch == NULL)
01253     goto failed_2;
01254   
01255   socket_transport->read_watch = _dbus_watch_new (fd,
01256                                                 DBUS_WATCH_READABLE,
01257                                                 FALSE,
01258                                                 NULL, NULL, NULL);
01259   if (socket_transport->read_watch == NULL)
01260     goto failed_3;
01261 
01262   if (!_dbus_transport_init_base (&socket_transport->base,
01263                                   &socket_vtable,
01264                                   server_guid, address))
01265     goto failed_4;
01266 
01267 #ifdef HAVE_UNIX_FD_PASSING
01268   _dbus_auth_set_unix_fd_possible(socket_transport->base.auth, _dbus_socket_can_pass_unix_fd(fd));
01269 #endif
01270 
01271   socket_transport->fd = fd;
01272   socket_transport->message_bytes_written = 0;
01273   
01274   /* These values should probably be tunable or something. */     
01275   socket_transport->max_bytes_read_per_iteration = 2048;
01276   socket_transport->max_bytes_written_per_iteration = 2048;
01277   
01278   return (DBusTransport*) socket_transport;
01279 
01280  failed_4:
01281   _dbus_watch_unref (socket_transport->read_watch);
01282  failed_3:
01283   _dbus_watch_unref (socket_transport->write_watch);
01284  failed_2:
01285   _dbus_string_free (&socket_transport->encoded_incoming);
01286  failed_1:
01287   _dbus_string_free (&socket_transport->encoded_outgoing);
01288  failed_0:
01289   dbus_free (socket_transport);
01290   return NULL;
01291 }
01292 
01304 DBusTransport*
01305 _dbus_transport_new_for_tcp_socket (const char     *host,
01306                                     const char     *port,
01307                                     const char     *family,
01308                                     const char     *noncefile,
01309                                     DBusError      *error)
01310 {
01311   int fd;
01312   DBusTransport *transport;
01313   DBusString address;
01314   
01315   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01316 
01317   if (!_dbus_string_init (&address))
01318     {
01319       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01320       return NULL;
01321     }
01322 
01323   if (host == NULL)
01324     host = "localhost";
01325 
01326   if (!_dbus_string_append (&address, noncefile ? "nonce-tcp:" : "tcp:"))
01327     goto error;
01328 
01329   if (!_dbus_string_append (&address, "host=") ||
01330       !_dbus_string_append (&address, host))
01331     goto error;
01332 
01333   if (!_dbus_string_append (&address, ",port=") ||
01334       !_dbus_string_append (&address, port))
01335     goto error;
01336 
01337   if (family != NULL &&
01338       (!_dbus_string_append (&address, "family=") ||
01339        !_dbus_string_append (&address, family)))
01340     goto error;
01341 
01342   if (noncefile != NULL &&
01343       (!_dbus_string_append (&address, "noncefile=") ||
01344        !_dbus_string_append (&address, noncefile)))
01345     goto error;
01346 
01347   fd = _dbus_connect_tcp_socket_with_nonce (host, port, family, noncefile, error);
01348   if (fd < 0)
01349     {
01350       _DBUS_ASSERT_ERROR_IS_SET (error);
01351       _dbus_string_free (&address);
01352       return NULL;
01353     }
01354 
01355   _dbus_verbose ("Successfully connected to tcp socket %s:%s\n",
01356                  host, port);
01357   
01358   transport = _dbus_transport_new_for_socket (fd, NULL, &address);
01359   _dbus_string_free (&address);
01360   if (transport == NULL)
01361     {
01362       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01363       _dbus_close_socket (fd, NULL);
01364       fd = -1;
01365     }
01366 
01367   return transport;
01368 
01369 error:
01370   _dbus_string_free (&address);
01371   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01372   return NULL;
01373 }
01374 
01383 DBusTransportOpenResult
01384 _dbus_transport_open_socket(DBusAddressEntry  *entry,
01385                             DBusTransport    **transport_p,                            
01386                             DBusError         *error)
01387 {
01388   const char *method;
01389   dbus_bool_t isTcp;
01390   dbus_bool_t isNonceTcp;
01391   
01392   method = dbus_address_entry_get_method (entry);
01393   _dbus_assert (method != NULL);
01394 
01395   isTcp = strcmp (method, "tcp") == 0;
01396   isNonceTcp = strcmp (method, "nonce-tcp") == 0;
01397 
01398   if (isTcp || isNonceTcp)
01399     {
01400       const char *host = dbus_address_entry_get_value (entry, "host");
01401       const char *port = dbus_address_entry_get_value (entry, "port");
01402       const char *family = dbus_address_entry_get_value (entry, "family");
01403       const char *noncefile = dbus_address_entry_get_value (entry, "noncefile");
01404 
01405       if ((isNonceTcp == TRUE) != (noncefile != NULL)) {
01406           _dbus_set_bad_address (error, method, "noncefile", NULL);
01407           return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
01408       }
01409 
01410       if (port == NULL)
01411         {
01412           _dbus_set_bad_address (error, method, "port", NULL);
01413           return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
01414         }
01415 
01416       *transport_p = _dbus_transport_new_for_tcp_socket (host, port, family, noncefile, error);
01417       if (*transport_p == NULL)
01418         {
01419           _DBUS_ASSERT_ERROR_IS_SET (error);
01420           return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
01421         }
01422       else
01423         {
01424           _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01425           return DBUS_TRANSPORT_OPEN_OK;
01426         }
01427     }
01428   else
01429     {
01430       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01431       return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
01432     }
01433 }
01434