Main Page | Modules | Data Structures | File List | Data Fields | Related Pages

dbus-transport-unix.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-transport-unix.c UNIX socket subclasses of DBusTransport
00003  *
00004  * Copyright (C) 2002, 2003  Red Hat Inc.
00005  *
00006  * Licensed under the Academic Free License version 2.0
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-unix.h"
00027 #include "dbus-transport-protected.h"
00028 #include "dbus-watch.h"
00029 #include <sys/types.h>
00030 #include <sys/time.h>
00031 #include <unistd.h>
00032 
00033 
00045 typedef struct DBusTransportUnix DBusTransportUnix;
00046 
00050 struct DBusTransportUnix
00051 {
00052   DBusTransport base;                   
00053   int fd;                               
00054   DBusWatch *read_watch;                
00055   DBusWatch *write_watch;               
00057   int max_bytes_read_per_iteration;     
00058   int max_bytes_written_per_iteration;  
00060   int message_bytes_written;            
00064   DBusString encoded_outgoing;          
00067   DBusString encoded_incoming;          
00070 };
00071 
00072 static void
00073 free_watches (DBusTransport *transport)
00074 {
00075   DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
00076   
00077   if (unix_transport->read_watch)
00078     {
00079       if (transport->connection)
00080         _dbus_connection_remove_watch (transport->connection,
00081                                        unix_transport->read_watch);
00082       _dbus_watch_invalidate (unix_transport->read_watch);
00083       _dbus_watch_unref (unix_transport->read_watch);
00084       unix_transport->read_watch = NULL;
00085     }
00086 
00087   if (unix_transport->write_watch)
00088     {
00089       if (transport->connection)
00090         _dbus_connection_remove_watch (transport->connection,
00091                                        unix_transport->write_watch);
00092       _dbus_watch_invalidate (unix_transport->write_watch);
00093       _dbus_watch_unref (unix_transport->write_watch);
00094       unix_transport->write_watch = NULL;
00095     }
00096 }
00097 
00098 static void
00099 unix_finalize (DBusTransport *transport)
00100 {
00101   DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
00102   
00103   free_watches (transport);
00104 
00105   _dbus_string_free (&unix_transport->encoded_outgoing);
00106   _dbus_string_free (&unix_transport->encoded_incoming);
00107   
00108   _dbus_transport_finalize_base (transport);
00109 
00110   _dbus_assert (unix_transport->read_watch == NULL);
00111   _dbus_assert (unix_transport->write_watch == NULL);
00112   
00113   dbus_free (transport);
00114 }
00115 
00116 static void
00117 check_write_watch (DBusTransport *transport)
00118 {
00119   DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
00120   dbus_bool_t need_write_watch;
00121 
00122   if (transport->connection == NULL)
00123     return;
00124 
00125   if (transport->disconnected)
00126     {
00127       _dbus_assert (unix_transport->write_watch == NULL);
00128       return;
00129     }
00130   
00131   _dbus_transport_ref (transport);
00132 
00133   if (_dbus_transport_get_is_authenticated (transport))
00134     need_write_watch = transport->messages_need_sending;
00135   else
00136     need_write_watch = transport->send_credentials_pending ||
00137       _dbus_auth_do_work (transport->auth) == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND;
00138 
00139   _dbus_connection_toggle_watch (transport->connection,
00140                                  unix_transport->write_watch,
00141                                  need_write_watch);
00142 
00143   _dbus_transport_unref (transport);
00144 }
00145 
00146 static void
00147 check_read_watch (DBusTransport *transport)
00148 {
00149   DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
00150   dbus_bool_t need_read_watch;
00151 
00152   if (transport->connection == NULL)
00153     return;
00154 
00155   if (transport->disconnected)
00156     {
00157       _dbus_assert (unix_transport->read_watch == NULL);
00158       return;
00159     }
00160   
00161   _dbus_transport_ref (transport);
00162 
00163   if (_dbus_transport_get_is_authenticated (transport))
00164     need_read_watch =
00165       _dbus_counter_get_value (transport->live_messages_size) < transport->max_live_messages_size;
00166   else
00167     need_read_watch = transport->receive_credentials_pending ||
00168       _dbus_auth_do_work (transport->auth) == DBUS_AUTH_STATE_WAITING_FOR_INPUT;
00169 
00170   _dbus_connection_toggle_watch (transport->connection,
00171                                  unix_transport->read_watch,
00172                                  need_read_watch);
00173 
00174   _dbus_transport_unref (transport);
00175 }
00176 
00177 static void
00178 do_io_error (DBusTransport *transport)
00179 {
00180   _dbus_transport_ref (transport);
00181   _dbus_transport_disconnect (transport);
00182   _dbus_transport_unref (transport);
00183 }
00184 
00185 /* return value is whether we successfully read any new data. */
00186 static dbus_bool_t
00187 read_data_into_auth (DBusTransport *transport,
00188                      dbus_bool_t   *oom)
00189 {
00190   DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
00191   DBusString *buffer;
00192   int bytes_read;
00193   
00194   *oom = FALSE;
00195 
00196   _dbus_auth_get_buffer (transport->auth, &buffer);
00197   
00198   bytes_read = _dbus_read (unix_transport->fd,
00199                            buffer, unix_transport->max_bytes_read_per_iteration);
00200 
00201   _dbus_auth_return_buffer (transport->auth, buffer,
00202                             bytes_read > 0 ? bytes_read : 0);
00203 
00204   if (bytes_read > 0)
00205     {
00206       _dbus_verbose (" read %d bytes in auth phase\n", bytes_read);
00207 
00208       return TRUE;
00209     }
00210   else if (bytes_read < 0)
00211     {
00212       /* EINTR already handled for us */
00213 
00214       if (errno == ENOMEM)
00215         {
00216           *oom = TRUE;
00217         }
00218       else if (errno == EAGAIN ||
00219                errno == EWOULDBLOCK)
00220         ; /* do nothing, just return FALSE below */
00221       else
00222         {
00223           _dbus_verbose ("Error reading from remote app: %s\n",
00224                          _dbus_strerror (errno));
00225           do_io_error (transport);
00226         }
00227 
00228       return FALSE;
00229     }
00230   else
00231     {
00232       _dbus_assert (bytes_read == 0);
00233       
00234       _dbus_verbose ("Disconnected from remote app\n");
00235       do_io_error (transport);
00236 
00237       return FALSE;
00238     }
00239 }
00240 
00241 /* Return value is whether we successfully wrote any bytes */
00242 static dbus_bool_t
00243 write_data_from_auth (DBusTransport *transport)
00244 {
00245   DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
00246   int bytes_written;
00247   const DBusString *buffer;
00248 
00249   if (!_dbus_auth_get_bytes_to_send (transport->auth,
00250                                      &buffer))
00251     return FALSE;
00252   
00253   bytes_written = _dbus_write (unix_transport->fd,
00254                                buffer,
00255                                0, _dbus_string_get_length (buffer));
00256 
00257   if (bytes_written > 0)
00258     {
00259       _dbus_auth_bytes_sent (transport->auth, bytes_written);
00260       return TRUE;
00261     }
00262   else if (bytes_written < 0)
00263     {
00264       /* EINTR already handled for us */
00265       
00266       if (errno == EAGAIN ||
00267           errno == EWOULDBLOCK)
00268         ;
00269       else
00270         {
00271           _dbus_verbose ("Error writing to remote app: %s\n",
00272                          _dbus_strerror (errno));
00273           do_io_error (transport);
00274         }
00275     }
00276 
00277   return FALSE;
00278 }
00279 
00280 static void
00281 exchange_credentials (DBusTransport *transport,
00282                       dbus_bool_t    do_reading,
00283                       dbus_bool_t    do_writing)
00284 {
00285   DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
00286 
00287   if (do_writing && transport->send_credentials_pending)
00288     {
00289       if (_dbus_send_credentials_unix_socket (unix_transport->fd,
00290                                               NULL))
00291         {
00292           transport->send_credentials_pending = FALSE;
00293         }
00294       else
00295         {
00296           _dbus_verbose ("Failed to write credentials\n");
00297           do_io_error (transport);
00298         }
00299     }
00300   
00301   if (do_reading && transport->receive_credentials_pending)
00302     {
00303       if (_dbus_read_credentials_unix_socket (unix_transport->fd,
00304                                                &transport->credentials,
00305                                                NULL))
00306         {
00307           transport->receive_credentials_pending = FALSE;
00308         }
00309       else
00310         {
00311           _dbus_verbose ("Failed to read credentials\n");
00312           do_io_error (transport);
00313         }
00314     }
00315 
00316   if (!(transport->send_credentials_pending ||
00317         transport->receive_credentials_pending))
00318     {
00319       _dbus_auth_set_credentials (transport->auth,
00320                                   &transport->credentials);
00321     }
00322 }
00323 
00324 static dbus_bool_t
00325 do_authentication (DBusTransport *transport,
00326                    dbus_bool_t    do_reading,
00327                    dbus_bool_t    do_writing)
00328 {
00329   dbus_bool_t oom;
00330   
00331   _dbus_transport_ref (transport);
00332 
00333   oom = FALSE;
00334   
00335   while (!_dbus_transport_get_is_authenticated (transport) &&
00336          _dbus_transport_get_is_connected (transport))
00337     {      
00338       exchange_credentials (transport, do_reading, do_writing);
00339       
00340       if (transport->send_credentials_pending ||
00341           transport->receive_credentials_pending)
00342         {
00343           _dbus_verbose ("send_credentials_pending = %d receive_credentials_pending = %d\n",
00344                          transport->send_credentials_pending,
00345                          transport->receive_credentials_pending);
00346           goto out;
00347         }
00348 
00349 #define TRANSPORT_SIDE(t) ((t)->is_server ? "server" : "client")
00350       switch (_dbus_auth_do_work (transport->auth))
00351         {
00352         case DBUS_AUTH_STATE_WAITING_FOR_INPUT:
00353           _dbus_verbose (" %s auth state: waiting for input\n",
00354                          TRANSPORT_SIDE (transport));
00355           if (!do_reading || !read_data_into_auth (transport, &oom))
00356             goto out;
00357           break;
00358       
00359         case DBUS_AUTH_STATE_WAITING_FOR_MEMORY:
00360           _dbus_verbose (" %s auth state: waiting for memory\n",
00361                          TRANSPORT_SIDE (transport));
00362           oom = TRUE;
00363           goto out;
00364           break;
00365       
00366         case DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND:
00367           _dbus_verbose (" %s auth state: bytes to send\n",
00368                          TRANSPORT_SIDE (transport));
00369           if (!do_writing || !write_data_from_auth (transport))
00370             goto out;
00371           break;
00372       
00373         case DBUS_AUTH_STATE_NEED_DISCONNECT:
00374           _dbus_verbose (" %s auth state: need to disconnect\n",
00375                          TRANSPORT_SIDE (transport));
00376           do_io_error (transport);
00377           break;
00378       
00379         case DBUS_AUTH_STATE_AUTHENTICATED_WITH_UNUSED_BYTES:
00380           _dbus_verbose (" %s auth state: auth with unused bytes\n",
00381                          TRANSPORT_SIDE (transport));
00382           /* We'll recover the unused bytes in dbus-transport.c */
00383           goto out;
00384           break;
00385           
00386         case DBUS_AUTH_STATE_AUTHENTICATED:
00387           _dbus_verbose (" %s auth state: authenticated\n",
00388                          TRANSPORT_SIDE (transport));
00389           break;
00390         }
00391     }
00392   
00393  out:
00394   check_read_watch (transport);
00395   check_write_watch (transport);
00396   _dbus_transport_unref (transport);
00397 
00398   if (oom)
00399     return FALSE;
00400   else
00401     return TRUE;
00402 }
00403 
00404 /* returns false on oom */
00405 static dbus_bool_t
00406 do_writing (DBusTransport *transport)
00407 {
00408   int total;
00409   DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
00410   dbus_bool_t oom;
00411   
00412   /* No messages without authentication! */
00413   if (!_dbus_transport_get_is_authenticated (transport))
00414     {
00415       _dbus_verbose ("Not authenticated, not writing anything\n");
00416       return TRUE;
00417     }
00418 
00419   if (transport->disconnected)
00420     {
00421       _dbus_verbose ("Not connected, not writing anything\n");
00422       return TRUE;
00423     }
00424 
00425 #if 0
00426   _dbus_verbose ("do_writing(), have_messages = %d\n",
00427                  _dbus_connection_have_messages_to_send (transport->connection));
00428 #endif
00429   
00430   oom = FALSE;
00431   total = 0;
00432 
00433   while (!transport->disconnected &&
00434          _dbus_connection_have_messages_to_send (transport->connection))
00435     {
00436       int bytes_written;
00437       DBusMessage *message;
00438       const DBusString *header;
00439       const DBusString *body;
00440       int header_len, body_len;
00441       int total_bytes_to_write;
00442       
00443       if (total > unix_transport->max_bytes_written_per_iteration)
00444         {
00445           _dbus_verbose ("%d bytes exceeds %d bytes written per iteration, returning\n",
00446                          total, unix_transport->max_bytes_written_per_iteration);
00447           goto out;
00448         }
00449 
00450       if (!dbus_watch_get_enabled (unix_transport->write_watch))
00451         {
00452           _dbus_verbose ("write watch disabled, not writing more stuff\n");
00453           goto out;
00454         }
00455       
00456       message = _dbus_connection_get_message_to_send (transport->connection);
00457       _dbus_assert (message != NULL);
00458       _dbus_message_lock (message);
00459 
00460 #if 0
00461       _dbus_verbose ("writing message %p\n", message);
00462 #endif
00463       
00464       _dbus_message_get_network_data (message,
00465                                       &header, &body);
00466 
00467       header_len = _dbus_string_get_length (header);
00468       body_len = _dbus_string_get_length (body);
00469 
00470       if (_dbus_auth_needs_encoding (transport->auth))
00471         {
00472           if (_dbus_string_get_length (&unix_transport->encoded_outgoing) == 0)
00473             {
00474               if (!_dbus_auth_encode_data (transport->auth,
00475                                            header, &unix_transport->encoded_outgoing))
00476                 {
00477                   oom = TRUE;
00478                   goto out;
00479                 }
00480               
00481               if (!_dbus_auth_encode_data (transport->auth,
00482                                            body, &unix_transport->encoded_outgoing))
00483                 {
00484                   _dbus_string_set_length (&unix_transport->encoded_outgoing, 0);
00485                   oom = TRUE;
00486                   goto out;
00487                 }
00488             }
00489           
00490           total_bytes_to_write = _dbus_string_get_length (&unix_transport->encoded_outgoing);
00491 
00492 #if 0
00493           _dbus_verbose ("encoded message is %d bytes\n",
00494                          total_bytes_to_write);
00495 #endif
00496           
00497           bytes_written =
00498             _dbus_write (unix_transport->fd,
00499                          &unix_transport->encoded_outgoing,
00500                          unix_transport->message_bytes_written,
00501                          total_bytes_to_write - unix_transport->message_bytes_written);
00502         }
00503       else
00504         {
00505           total_bytes_to_write = header_len + body_len;
00506 
00507 #if 0
00508           _dbus_verbose ("message is %d bytes\n",
00509                          total_bytes_to_write);          
00510 #endif
00511           
00512           if (unix_transport->message_bytes_written < header_len)
00513             {
00514               bytes_written =
00515                 _dbus_write_two (unix_transport->fd,
00516                                  header,
00517                                  unix_transport->message_bytes_written,
00518                                  header_len - unix_transport->message_bytes_written,
00519                                  body,
00520                                  0, body_len);
00521             }
00522           else
00523             {
00524               bytes_written =
00525                 _dbus_write (unix_transport->fd,
00526                              body,
00527                              (unix_transport->message_bytes_written - header_len),
00528                              body_len -
00529                              (unix_transport->message_bytes_written - header_len));
00530             }
00531         }
00532 
00533       if (bytes_written < 0)
00534         {
00535           /* EINTR already handled for us */
00536           
00537           if (errno == EAGAIN ||
00538               errno == EWOULDBLOCK)
00539             goto out;
00540           else
00541             {
00542               _dbus_verbose ("Error writing to remote app: %s\n",
00543                              _dbus_strerror (errno));
00544               do_io_error (transport);
00545               goto out;
00546             }
00547         }
00548       else
00549         {
00550           _dbus_verbose (" wrote %d bytes of %d\n", bytes_written,
00551                          total_bytes_to_write);
00552           
00553           total += bytes_written;
00554           unix_transport->message_bytes_written += bytes_written;
00555 
00556           _dbus_assert (unix_transport->message_bytes_written <=
00557                         total_bytes_to_write);
00558           
00559           if (unix_transport->message_bytes_written == total_bytes_to_write)
00560             {
00561               unix_transport->message_bytes_written = 0;
00562               _dbus_string_set_length (&unix_transport->encoded_outgoing, 0);
00563 
00564               _dbus_connection_message_sent (transport->connection,
00565                                              message);
00566             }
00567         }
00568     }
00569 
00570  out:
00571   if (oom)
00572     return FALSE;
00573   else
00574     return TRUE;
00575 }
00576 
00577 /* returns false on out-of-memory */
00578 static dbus_bool_t
00579 do_reading (DBusTransport *transport)
00580 {
00581   DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
00582   DBusString *buffer;
00583   int bytes_read;
00584   int total;
00585   dbus_bool_t oom;
00586 
00587   /* No messages without authentication! */
00588   if (!_dbus_transport_get_is_authenticated (transport))
00589     return TRUE;
00590 
00591   oom = FALSE;
00592   
00593   total = 0;
00594 
00595  again:
00596   
00597   /* See if we've exceeded max messages and need to disable reading */
00598   check_read_watch (transport);
00599   
00600   if (total > unix_transport->max_bytes_read_per_iteration)
00601     {
00602       _dbus_verbose ("%d bytes exceeds %d bytes read per iteration, returning\n",
00603                      total, unix_transport->max_bytes_read_per_iteration);
00604       goto out;
00605     }
00606 
00607   _dbus_assert (unix_transport->read_watch != NULL ||
00608                 transport->disconnected);
00609   
00610   if (transport->disconnected)
00611     goto out;
00612 
00613   if (!dbus_watch_get_enabled (unix_transport->read_watch))
00614     return TRUE;
00615   
00616   if (_dbus_auth_needs_decoding (transport->auth))
00617     {
00618       if (_dbus_string_get_length (&unix_transport->encoded_incoming) > 0)
00619         bytes_read = _dbus_string_get_length (&unix_transport->encoded_incoming);
00620       else
00621         bytes_read = _dbus_read (unix_transport->fd,
00622                                  &unix_transport->encoded_incoming,
00623                                  unix_transport->max_bytes_read_per_iteration);
00624 
00625       _dbus_assert (_dbus_string_get_length (&unix_transport->encoded_incoming) ==
00626                     bytes_read);
00627       
00628       if (bytes_read > 0)
00629         {
00630           int orig_len;
00631           
00632           _dbus_message_loader_get_buffer (transport->loader,
00633                                            &buffer);
00634 
00635           orig_len = _dbus_string_get_length (buffer);
00636           
00637           if (!_dbus_auth_decode_data (transport->auth,
00638                                        &unix_transport->encoded_incoming,
00639                                        buffer))
00640             {
00641               _dbus_verbose ("Out of memory decoding incoming data\n");
00642               oom = TRUE;
00643               goto out;
00644             }
00645 
00646           _dbus_message_loader_return_buffer (transport->loader,
00647                                               buffer,
00648                                               _dbus_string_get_length (buffer) - orig_len);
00649 
00650           _dbus_string_set_length (&unix_transport->encoded_incoming, 0);
00651         }
00652     }
00653   else
00654     {
00655       _dbus_message_loader_get_buffer (transport->loader,
00656                                        &buffer);
00657       
00658       bytes_read = _dbus_read (unix_transport->fd,
00659                                buffer, unix_transport->max_bytes_read_per_iteration);
00660       
00661       _dbus_message_loader_return_buffer (transport->loader,
00662                                           buffer,
00663                                           bytes_read < 0 ? 0 : bytes_read);
00664     }
00665   
00666   if (bytes_read < 0)
00667     {
00668       /* EINTR already handled for us */
00669 
00670       if (errno == ENOMEM)
00671         {
00672           _dbus_verbose ("Out of memory in read()/do_reading()\n");
00673           oom = TRUE;
00674           goto out;
00675         }
00676       else if (errno == EAGAIN ||
00677                errno == EWOULDBLOCK)
00678         goto out;
00679       else
00680         {
00681           _dbus_verbose ("Error reading from remote app: %s\n",
00682                          _dbus_strerror (errno));
00683           do_io_error (transport);
00684           goto out;
00685         }
00686     }
00687   else if (bytes_read == 0)
00688     {
00689       _dbus_verbose ("Disconnected from remote app\n");
00690       do_io_error (transport);
00691       goto out;
00692     }
00693   else
00694     {
00695       _dbus_verbose (" read %d bytes\n", bytes_read);
00696       
00697       total += bytes_read;      
00698 
00699       if (_dbus_transport_queue_messages (transport) == DBUS_DISPATCH_NEED_MEMORY)
00700         {
00701           oom = TRUE;
00702           _dbus_verbose (" out of memory when queueing messages we just read in the transport\n");
00703           goto out;
00704         }
00705       
00706       /* Try reading more data until we get EAGAIN and return, or
00707        * exceed max bytes per iteration.  If in blocking mode of
00708        * course we'll block instead of returning.
00709        */
00710       goto again;
00711     }
00712 
00713  out:
00714   if (oom)
00715     return FALSE;
00716   else
00717     return TRUE;
00718 }
00719 
00720 static dbus_bool_t
00721 unix_handle_watch (DBusTransport *transport,
00722                    DBusWatch     *watch,
00723                    unsigned int   flags)
00724 {
00725   DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
00726 
00727   _dbus_assert (watch == unix_transport->read_watch ||
00728                 watch == unix_transport->write_watch);
00729   
00730   if (watch == unix_transport->read_watch &&
00731       (flags & DBUS_WATCH_READABLE))
00732     {
00733 #if 1
00734       _dbus_verbose ("handling read watch\n");
00735 #endif
00736       if (!do_authentication (transport, TRUE, FALSE))
00737         return FALSE;
00738       
00739       if (!do_reading (transport))
00740         {
00741           _dbus_verbose ("no memory to read\n");
00742           return FALSE;
00743         }
00744     }
00745   else if (watch == unix_transport->write_watch &&
00746            (flags & DBUS_WATCH_WRITABLE))
00747     {
00748 #if 0
00749       _dbus_verbose ("handling write watch, messages_need_sending = %d\n",
00750                      transport->messages_need_sending);
00751 #endif
00752       if (!do_authentication (transport, FALSE, TRUE))
00753         return FALSE;
00754       
00755       if (!do_writing (transport))
00756         {
00757           _dbus_verbose ("no memory to write\n");
00758           return FALSE;
00759         }
00760     }
00761 #ifdef DBUS_ENABLE_VERBOSE_MODE
00762   else
00763     {
00764       if (watch == unix_transport->read_watch)
00765         _dbus_verbose ("asked to handle read watch with non-read condition 0x%x\n",
00766                        flags);
00767       else if (watch == unix_transport->write_watch)
00768         _dbus_verbose ("asked to handle write watch with non-write condition 0x%x\n",
00769                        flags);
00770       else
00771         _dbus_verbose ("asked to handle watch %p on fd %d that we don't recognize\n",
00772                        watch, dbus_watch_get_fd (watch));
00773     }
00774 #endif /* DBUS_ENABLE_VERBOSE_MODE */
00775 
00776   if (flags & (DBUS_WATCH_HANGUP | DBUS_WATCH_ERROR))
00777     {
00778       _dbus_transport_disconnect (transport);
00779       return TRUE;
00780     }
00781   
00782   return TRUE;
00783 }
00784 
00785 static void
00786 unix_disconnect (DBusTransport *transport)
00787 {
00788   DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
00789   
00790   free_watches (transport);
00791   
00792   _dbus_close (unix_transport->fd, NULL);
00793   unix_transport->fd = -1;
00794 }
00795 
00796 static dbus_bool_t
00797 unix_connection_set (DBusTransport *transport)
00798 {
00799   DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
00800 
00801   _dbus_watch_set_handler (unix_transport->write_watch,
00802                            _dbus_connection_handle_watch,
00803                            transport->connection, NULL);
00804 
00805   _dbus_watch_set_handler (unix_transport->read_watch,
00806                            _dbus_connection_handle_watch,
00807                            transport->connection, NULL);
00808   
00809   if (!_dbus_connection_add_watch (transport->connection,
00810                                    unix_transport->write_watch))
00811     return FALSE;
00812 
00813   if (!_dbus_connection_add_watch (transport->connection,
00814                                    unix_transport->read_watch))
00815     {
00816       _dbus_connection_remove_watch (transport->connection,
00817                                      unix_transport->write_watch);
00818       return FALSE;
00819     }
00820 
00821   check_read_watch (transport);
00822   check_write_watch (transport);
00823 
00824   return TRUE;
00825 }
00826 
00827 static void
00828 unix_messages_pending (DBusTransport *transport,
00829                        int            messages_pending)
00830 {
00831   check_write_watch (transport);
00832 }
00833 
00834 /* FIXME use _dbus_poll(), not select() */
00842 static  void
00843 unix_do_iteration (DBusTransport *transport,
00844                    unsigned int   flags,
00845                    int            timeout_milliseconds)
00846 {
00847   DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
00848   fd_set read_set;
00849   fd_set write_set;
00850   dbus_bool_t do_select;
00851   int select_res;
00852 
00853   _dbus_verbose (" iteration flags = %s%s timeout = %d read_watch = %p write_watch = %p\n",
00854                  flags & DBUS_ITERATION_DO_READING ? "read" : "",
00855                  flags & DBUS_ITERATION_DO_WRITING ? "write" : "",
00856                  timeout_milliseconds,
00857                  unix_transport->read_watch,
00858                  unix_transport->write_watch);
00859   
00860   /* "again" has to be up here because on EINTR the fd sets become
00861    * undefined
00862    */
00863  again:
00864   
00865   do_select = FALSE;
00866 
00867   /* the passed in DO_READING/DO_WRITING flags indicate whether to
00868    * read/write messages, but regardless of those we may need to block
00869    * for reading/writing to do auth.  But if we do reading for auth,
00870    * we don't want to read any messages yet if not given DO_READING.
00871    *
00872    * Also, if read_watch == NULL or write_watch == NULL, we don't
00873    * want to read/write so don't.
00874    */
00875 
00876   FD_ZERO (&read_set);
00877   FD_ZERO (&write_set);
00878   
00879   if (_dbus_transport_get_is_authenticated (transport))
00880     {
00881       if (unix_transport->read_watch &&
00882           (flags & DBUS_ITERATION_DO_READING))
00883         {
00884           FD_SET (unix_transport->fd, &read_set);
00885           do_select = TRUE;
00886         }
00887       
00888       if (unix_transport->write_watch &&
00889           (flags & DBUS_ITERATION_DO_WRITING))
00890         {
00891           FD_SET (unix_transport->fd, &write_set);
00892           do_select = TRUE;
00893         }
00894     }
00895   else
00896     {
00897       DBusAuthState auth_state;
00898       
00899       auth_state = _dbus_auth_do_work (transport->auth);
00900 
00901       if (transport->receive_credentials_pending ||
00902           auth_state == DBUS_AUTH_STATE_WAITING_FOR_INPUT)
00903         {
00904           FD_SET (unix_transport->fd, &read_set);
00905           do_select = TRUE;
00906         }
00907 
00908       if (transport->send_credentials_pending ||
00909           auth_state == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND)
00910         {
00911           FD_SET (unix_transport->fd, &write_set);
00912           do_select = TRUE;
00913         }
00914     } 
00915 
00916   if (do_select)
00917     {
00918       fd_set err_set;
00919       struct timeval timeout;
00920       dbus_bool_t use_timeout;
00921       
00922       FD_ZERO (&err_set);
00923       FD_SET (unix_transport->fd, &err_set);
00924   
00925       if (flags & DBUS_ITERATION_BLOCK)
00926         {
00927           if (timeout_milliseconds >= 0)
00928             {
00929               timeout.tv_sec = timeout_milliseconds / 1000;
00930               timeout.tv_usec = (timeout_milliseconds % 1000) * 1000;
00931               
00932               /* Always use timeout if one is passed in. */
00933               use_timeout = TRUE;
00934             }
00935           else
00936             {
00937               use_timeout = FALSE; /* NULL timeout to block forever */
00938             }
00939         }
00940       else
00941         {
00942           /* 0 timeout to not block */
00943           timeout.tv_sec = 0;
00944           timeout.tv_usec = 0;
00945           use_timeout = TRUE;
00946         }
00947 
00948       /* For blocking selects we drop the connection lock here
00949        * to avoid blocking out connection access during a potentially
00950        * indefinite blocking call. The io path is still protected
00951        * by the io_path_cond condvar, so we won't reenter this.
00952        */
00953       if (flags & DBUS_ITERATION_BLOCK)
00954         _dbus_connection_unlock (transport->connection);
00955       
00956       select_res = select (unix_transport->fd + 1,
00957                            &read_set, &write_set, &err_set,
00958                            use_timeout ? &timeout : NULL);
00959 
00960       if (flags & DBUS_ITERATION_BLOCK)
00961         _dbus_connection_lock (transport->connection);
00962       
00963       
00964       if (select_res >= 0)
00965         {
00966           if (FD_ISSET (unix_transport->fd, &err_set))
00967             do_io_error (transport);
00968           else
00969             {
00970               dbus_bool_t need_read = FD_ISSET (unix_transport->fd, &read_set);
00971               dbus_bool_t need_write = FD_ISSET (unix_transport->fd, &write_set);
00972 
00973               _dbus_verbose ("in iteration, need_read=%d need_write=%d\n",
00974                              need_read, need_write);
00975               do_authentication (transport, need_read, need_write);
00976                                  
00977               if (need_read && (flags & DBUS_ITERATION_DO_READING))
00978                 do_reading (transport);
00979               if (need_write && (flags & DBUS_ITERATION_DO_WRITING))
00980                 do_writing (transport);
00981             }
00982         }
00983       else if (errno == EINTR)
00984         goto again;
00985       else
00986         {
00987           _dbus_verbose ("Error from select(): %s\n",
00988                          _dbus_strerror (errno));
00989         }
00990     }
00991 }
00992 
00993 static void
00994 unix_live_messages_changed (DBusTransport *transport)
00995 {
00996   /* See if we should look for incoming messages again */
00997   check_read_watch (transport);
00998 }
00999 
01000 static DBusTransportVTable unix_vtable = {
01001   unix_finalize,
01002   unix_handle_watch,
01003   unix_disconnect,
01004   unix_connection_set,
01005   unix_messages_pending,
01006   unix_do_iteration,
01007   unix_live_messages_changed
01008 };
01009 
01021 DBusTransport*
01022 _dbus_transport_new_for_fd (int               fd,
01023                             dbus_bool_t       server,
01024                             const DBusString *address)
01025 {
01026   DBusTransportUnix *unix_transport;
01027   
01028   unix_transport = dbus_new0 (DBusTransportUnix, 1);
01029   if (unix_transport == NULL)
01030     return NULL;
01031 
01032   if (!_dbus_string_init (&unix_transport->encoded_outgoing))
01033     goto failed_0;
01034 
01035   if (!_dbus_string_init (&unix_transport->encoded_incoming))
01036     goto failed_1;
01037   
01038   unix_transport->write_watch = _dbus_watch_new (fd,
01039                                                  DBUS_WATCH_WRITABLE,
01040                                                  FALSE,
01041                                                  NULL, NULL, NULL);
01042   if (unix_transport->write_watch == NULL)
01043     goto failed_2;
01044   
01045   unix_transport->read_watch = _dbus_watch_new (fd,
01046                                                 DBUS_WATCH_READABLE,
01047                                                 FALSE,
01048                                                 NULL, NULL, NULL);
01049   if (unix_transport->read_watch == NULL)
01050     goto failed_3;
01051   
01052   if (!_dbus_transport_init_base (&unix_transport->base,
01053                                   &unix_vtable,
01054                                   server, address))
01055     goto failed_4;
01056   
01057   unix_transport->fd = fd;
01058   unix_transport->message_bytes_written = 0;
01059   
01060   /* These values should probably be tunable or something. */     
01061   unix_transport->max_bytes_read_per_iteration = 2048;
01062   unix_transport->max_bytes_written_per_iteration = 2048;
01063   
01064   return (DBusTransport*) unix_transport;
01065 
01066  failed_4:
01067   _dbus_watch_unref (unix_transport->read_watch);
01068  failed_3:
01069   _dbus_watch_unref (unix_transport->write_watch);
01070  failed_2:
01071   _dbus_string_free (&unix_transport->encoded_incoming);
01072  failed_1:
01073   _dbus_string_free (&unix_transport->encoded_outgoing);
01074  failed_0:
01075   dbus_free (unix_transport);
01076   return NULL;
01077 }
01078 
01091 DBusTransport*
01092 _dbus_transport_new_for_domain_socket (const char     *path,
01093                                        dbus_bool_t     abstract,
01094                                        DBusError      *error)
01095 {
01096   int fd;
01097   DBusTransport *transport;
01098   DBusString address;
01099   
01100   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01101 
01102   if (!_dbus_string_init (&address))
01103     {
01104       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01105       return NULL;
01106     }
01107 
01108   fd = -1;
01109 
01110   if ((abstract &&
01111        !_dbus_string_append (&address, "unix:abstract=")) ||
01112       (!abstract &&
01113        !_dbus_string_append (&address, "unix:path=")) ||
01114       !_dbus_string_append (&address, path))
01115     {
01116       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01117       goto failed_0;
01118     }
01119   
01120   fd = _dbus_connect_unix_socket (path, abstract, error);
01121   if (fd < 0)
01122     {
01123       _DBUS_ASSERT_ERROR_IS_SET (error);
01124       goto failed_0;
01125     }
01126 
01127   _dbus_fd_set_close_on_exec (fd);
01128   
01129   _dbus_verbose ("Successfully connected to unix socket %s\n",
01130                  path);
01131 
01132   transport = _dbus_transport_new_for_fd (fd, FALSE, &address);
01133   if (transport == NULL)
01134     {
01135       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01136       goto failed_1;
01137     }
01138   
01139   _dbus_string_free (&address);
01140   
01141   return transport;
01142 
01143  failed_1:
01144   _dbus_close (fd, NULL);
01145  failed_0:
01146   _dbus_string_free (&address);
01147   return NULL;
01148 }
01149 
01158 DBusTransport*
01159 _dbus_transport_new_for_tcp_socket (const char     *host,
01160                                     dbus_int32_t    port,
01161                                     DBusError      *error)
01162 {
01163   int fd;
01164   DBusTransport *transport;
01165   DBusString address;
01166   
01167   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01168 
01169   if (!_dbus_string_init (&address))
01170     {
01171       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01172       return NULL;
01173     }
01174   
01175   if (!_dbus_string_append (&address, "tcp:host=") ||
01176       !_dbus_string_append (&address, host) ||
01177       !_dbus_string_append (&address, ",port=") ||
01178       !_dbus_string_append_int (&address, port))
01179     {
01180       _dbus_string_free (&address);
01181       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01182       return NULL;
01183     }
01184   
01185   fd = _dbus_connect_tcp_socket (host, port, error);
01186   if (fd < 0)
01187     {
01188       _DBUS_ASSERT_ERROR_IS_SET (error);
01189       _dbus_string_free (&address);
01190       return NULL;
01191     }
01192 
01193   _dbus_fd_set_close_on_exec (fd);
01194   
01195   _dbus_verbose ("Successfully connected to tcp socket %s:%d\n",
01196                  host, port);
01197   
01198   transport = _dbus_transport_new_for_fd (fd, FALSE, &address);
01199   if (transport == NULL)
01200     {
01201       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01202       _dbus_close (fd, NULL);
01203       _dbus_string_free (&address);
01204       fd = -1;
01205     }
01206 
01207   _dbus_string_free (&address);
01208   
01209   return transport;
01210 }
01211 

Generated on Sun Mar 21 03:52:06 2004 for D-BUS by doxygen 1.3.6-20040222