• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List

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

Generated on Thu Oct 4 2012 08:02:56 for D-Bus by  doxygen 1.7.1