dbus-transport-socket.c

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

Generated on Fri Jul 20 01:11:05 2007 for D-Bus by  doxygen 1.4.6