dbus-server-socket.c

00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-server-socket.c Server implementation for sockets
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-server-socket.h"
00026 #include "dbus-transport-socket.h"
00027 #include "dbus-connection-internal.h"
00028 #include "dbus-string.h"
00029 
00041 typedef struct DBusServerSocket DBusServerSocket;
00042 
00047 struct DBusServerSocket
00048 {
00049   DBusServer base;   
00050   int n_fds;         
00051   int *fds;          
00052   DBusWatch **watch; 
00053   char *socket_name; 
00054 };
00055 
00056 static void
00057 socket_finalize (DBusServer *server)
00058 {
00059   DBusServerSocket *socket_server = (DBusServerSocket*) server;
00060   int i;
00061   
00062   _dbus_server_finalize_base (server);
00063 
00064   for (i = 0 ; i < socket_server->n_fds ; i++)
00065     if (socket_server->watch[i])
00066       {
00067         _dbus_watch_unref (socket_server->watch[i]);
00068         socket_server->watch[i] = NULL;
00069       }
00070   
00071   dbus_free (socket_server->fds);
00072   dbus_free (socket_server->watch);
00073   dbus_free (socket_server->socket_name);
00074   dbus_free (server);
00075 }
00076 
00077 /* Return value is just for memory, not other failures. */
00078 static dbus_bool_t
00079 handle_new_client_fd_and_unlock (DBusServer *server,
00080                                  int         client_fd)
00081 {
00082   DBusConnection *connection;
00083   DBusTransport *transport;
00084   DBusNewConnectionFunction new_connection_function;
00085   void *new_connection_data;
00086   
00087   _dbus_verbose ("Creating new client connection with fd %d\n", client_fd);
00088 
00089   HAVE_LOCK_CHECK (server);
00090   
00091   if (!_dbus_set_fd_nonblocking (client_fd, NULL))
00092     {
00093       SERVER_UNLOCK (server);
00094       return TRUE;
00095     }
00096   
00097   transport = _dbus_transport_new_for_socket (client_fd, &server->guid_hex, NULL);
00098   if (transport == NULL)
00099     {
00100       _dbus_close_socket (client_fd, NULL);
00101       SERVER_UNLOCK (server);
00102       return FALSE;
00103     }
00104 
00105   if (!_dbus_transport_set_auth_mechanisms (transport,
00106                                             (const char **) server->auth_mechanisms))
00107     {
00108       _dbus_transport_unref (transport);
00109       SERVER_UNLOCK (server);
00110       return FALSE;
00111     }
00112   
00113   /* note that client_fd is now owned by the transport, and will be
00114    * closed on transport disconnection/finalization
00115    */
00116   
00117   connection = _dbus_connection_new_for_transport (transport);
00118   _dbus_transport_unref (transport);
00119   transport = NULL; /* now under the connection lock */
00120   
00121   if (connection == NULL)
00122     {
00123       SERVER_UNLOCK (server);
00124       return FALSE;
00125     }
00126   
00127   /* See if someone wants to handle this new connection, self-referencing
00128    * for paranoia.
00129    */
00130   new_connection_function = server->new_connection_function;
00131   new_connection_data = server->new_connection_data;
00132 
00133   _dbus_server_ref_unlocked (server);
00134   SERVER_UNLOCK (server);
00135   
00136   if (new_connection_function)
00137     {
00138       (* new_connection_function) (server, connection,
00139                                    new_connection_data);
00140     }
00141   dbus_server_unref (server);
00142   
00143   /* If no one grabbed a reference, the connection will die. */
00144   _dbus_connection_close_if_only_one_ref (connection);
00145   dbus_connection_unref (connection);
00146 
00147   return TRUE;
00148 }
00149 
00150 static dbus_bool_t
00151 socket_handle_watch (DBusWatch    *watch,
00152                    unsigned int  flags,
00153                    void         *data)
00154 {
00155   DBusServer *server = data;
00156 #ifndef DBUS_DISABLE_ASSERT
00157   DBusServerSocket *socket_server = data;
00158   int i;
00159   dbus_bool_t found = FALSE;
00160 #endif
00161 
00162   SERVER_LOCK (server);
00163   
00164 #ifndef DBUS_DISABLE_ASSERT
00165   for (i = 0 ; i < socket_server->n_fds ; i++)
00166     {
00167       if (socket_server->watch[i] == watch)
00168         found = TRUE;
00169     }
00170   _dbus_assert (found);
00171 #endif
00172 
00173   _dbus_verbose ("Handling client connection, flags 0x%x\n", flags);
00174   
00175   if (flags & DBUS_WATCH_READABLE)
00176     {
00177       int client_fd;
00178       int listen_fd;
00179       
00180       listen_fd = dbus_watch_get_socket (watch);
00181 
00182       client_fd = _dbus_accept (listen_fd);
00183       
00184       if (client_fd < 0)
00185         {
00186           /* EINTR handled for us */
00187           
00188           if (_dbus_get_is_errno_eagain_or_ewouldblock ())
00189             _dbus_verbose ("No client available to accept after all\n");
00190           else
00191             _dbus_verbose ("Failed to accept a client connection: %s\n",
00192                            _dbus_strerror_from_errno ());
00193 
00194           SERVER_UNLOCK (server);
00195         }
00196       else
00197         {
00198           _dbus_fd_set_close_on_exec (client_fd);         
00199 
00200           if (!handle_new_client_fd_and_unlock (server, client_fd))
00201             _dbus_verbose ("Rejected client connection due to lack of memory\n");
00202         }
00203     }
00204 
00205   if (flags & DBUS_WATCH_ERROR)
00206     _dbus_verbose ("Error on server listening socket\n");
00207 
00208   if (flags & DBUS_WATCH_HANGUP)
00209     _dbus_verbose ("Hangup on server listening socket\n");
00210 
00211   return TRUE;
00212 }
00213   
00214 static void
00215 socket_disconnect (DBusServer *server)
00216 {
00217   DBusServerSocket *socket_server = (DBusServerSocket*) server;
00218   int i;
00219 
00220   HAVE_LOCK_CHECK (server);
00221   
00222   for (i = 0 ; i < socket_server->n_fds ; i++)
00223     {
00224       if (socket_server->watch[i])
00225         {
00226           _dbus_server_remove_watch (server,
00227                                      socket_server->watch[i]);
00228           _dbus_watch_unref (socket_server->watch[i]);
00229           socket_server->watch[i] = NULL;
00230         }
00231 
00232       _dbus_close_socket (socket_server->fds[i], NULL);
00233       socket_server->fds[i] = -1;
00234     }
00235 
00236   if (socket_server->socket_name != NULL)
00237     {
00238       DBusString tmp;
00239       _dbus_string_init_const (&tmp, socket_server->socket_name);
00240       _dbus_delete_file (&tmp, NULL);
00241     }
00242 
00243   HAVE_LOCK_CHECK (server);
00244 }
00245 
00246 static const DBusServerVTable socket_vtable = {
00247   socket_finalize,
00248   socket_disconnect
00249 };
00250 
00265 DBusServer*
00266 _dbus_server_new_for_socket (int              *fds,
00267                              int               n_fds,
00268                              const DBusString *address)
00269 {
00270   DBusServerSocket *socket_server;
00271   DBusServer *server;
00272   int i;
00273   
00274   socket_server = dbus_new0 (DBusServerSocket, 1);
00275   if (socket_server == NULL)
00276     return NULL;
00277 
00278   socket_server->fds = dbus_new (int, n_fds);
00279   if (!socket_server->fds)
00280     goto failed_0;
00281 
00282   socket_server->watch = dbus_new0 (DBusWatch *, n_fds);
00283   if (!socket_server->watch)
00284     goto failed_1;
00285 
00286   for (i = 0 ; i < n_fds ; i++)
00287     {
00288       DBusWatch *watch;
00289 
00290       watch = _dbus_watch_new (fds[i],
00291                                DBUS_WATCH_READABLE,
00292                                TRUE,
00293                                socket_handle_watch, socket_server,
00294                                NULL);
00295       if (watch == NULL)
00296         goto failed_2;
00297 
00298       socket_server->n_fds++;
00299       socket_server->fds[i] = fds[i];
00300       socket_server->watch[i] = watch;
00301     }
00302 
00303   if (!_dbus_server_init_base (&socket_server->base,
00304                                &socket_vtable, address))
00305     goto failed_2;
00306 
00307   server = (DBusServer*)socket_server;
00308 
00309   SERVER_LOCK (server);
00310   
00311   for (i = 0 ; i < n_fds ; i++)
00312     {
00313       if (!_dbus_server_add_watch (&socket_server->base,
00314                                    socket_server->watch[i]))
00315         {
00316           int j;
00317           for (j = 0 ; j < i ; j++)
00318             _dbus_server_remove_watch (server,
00319                                        socket_server->watch[j]);
00320 
00321           SERVER_UNLOCK (server);
00322           _dbus_server_finalize_base (&socket_server->base);
00323           goto failed_2;
00324         }
00325     }
00326 
00327   SERVER_UNLOCK (server);
00328   
00329   return (DBusServer*) socket_server;
00330 
00331  failed_2:
00332   for (i = 0 ; i < n_fds ; i++)
00333     {
00334       if (socket_server->watch[i] != NULL)
00335         {
00336           _dbus_watch_unref (socket_server->watch[i]);
00337           socket_server->watch[i] = NULL;
00338         }
00339     }
00340   dbus_free (socket_server->watch);
00341 
00342  failed_1:
00343   dbus_free (socket_server->fds);
00344 
00345  failed_0:
00346   dbus_free (socket_server);
00347   return NULL;
00348 }
00349 
00368 DBusServer*
00369 _dbus_server_new_for_tcp_socket (const char     *host,
00370                                  const char     *bind,
00371                                  const char     *port,
00372                                  const char     *family,
00373                                  DBusError      *error)
00374 {
00375   DBusServer *server;
00376   int *listen_fds = NULL;
00377   int nlisten_fds = 0, i;
00378   DBusString address;
00379   DBusString host_str;
00380   DBusString port_str;
00381   
00382   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00383 
00384   if (!_dbus_string_init (&address))
00385     {
00386       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00387       return NULL;
00388     }
00389 
00390   if (!_dbus_string_init (&port_str))
00391     {
00392       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00393       goto failed_0;
00394     }
00395 
00396   if (host == NULL)
00397     host = "localhost";
00398 
00399   if (port == NULL)
00400     port = "0";
00401 
00402   if (bind == NULL)
00403     bind = host;
00404   else if (strcmp (bind, "*") == 0)
00405     bind = NULL;
00406 
00407   nlisten_fds =_dbus_listen_tcp_socket (bind, port, family,
00408                                         &port_str,
00409                                         &listen_fds, error);
00410   if (nlisten_fds <= 0)
00411     {
00412       _DBUS_ASSERT_ERROR_IS_SET(error);
00413       goto failed_1;
00414     }
00415 
00416   for (i = 0 ; i < nlisten_fds ; i++)
00417     _dbus_fd_set_close_on_exec (listen_fds[i]);
00418 
00419   _dbus_string_init_const (&host_str, host);
00420   if (!_dbus_string_append (&address, "tcp:host=") ||
00421       !_dbus_address_append_escaped (&address, &host_str) ||
00422       !_dbus_string_append (&address, ",port=") ||
00423       !_dbus_string_append (&address, _dbus_string_get_const_data(&port_str)))
00424     {
00425       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00426       goto failed_2;
00427     }
00428   if (family &&
00429       (!_dbus_string_append (&address, ",family=") ||
00430        !_dbus_string_append (&address, family)))
00431     {
00432       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00433       goto failed_2;
00434     }
00435   
00436   server = _dbus_server_new_for_socket (listen_fds, nlisten_fds, &address);
00437   if (server == NULL)
00438     {
00439       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00440       goto failed_2;
00441     }
00442 
00443   _dbus_string_free (&port_str);
00444   _dbus_string_free (&address);
00445   dbus_free(listen_fds);
00446 
00447   return server;
00448 
00449  failed_2:
00450   for (i = 0 ; i < nlisten_fds ; i++)
00451     _dbus_close_socket (listen_fds[i], NULL);
00452   dbus_free(listen_fds);
00453 
00454  failed_1:
00455   _dbus_string_free (&port_str);
00456 
00457  failed_0:
00458   _dbus_string_free (&address);
00459 
00460   return NULL;
00461 }
00462 
00475 DBusServerListenResult
00476 _dbus_server_listen_socket (DBusAddressEntry *entry,
00477                             DBusServer      **server_p,
00478                             DBusError        *error)
00479 {
00480   const char *method;
00481 
00482   *server_p = NULL;
00483   
00484   method = dbus_address_entry_get_method (entry);
00485   
00486   if (strcmp (method, "tcp") == 0)
00487     {
00488       const char *host;
00489       const char *port;
00490       const char *bind;
00491       const char *family;
00492 
00493       host = dbus_address_entry_get_value (entry, "host");
00494       bind = dbus_address_entry_get_value (entry, "bind");
00495       port = dbus_address_entry_get_value (entry, "port");
00496       family = dbus_address_entry_get_value (entry, "family");
00497 
00498       *server_p = _dbus_server_new_for_tcp_socket (host, bind, port,
00499                                                    family, error);
00500 
00501       if (*server_p)
00502         {
00503           _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00504           return DBUS_SERVER_LISTEN_OK;
00505         }
00506       else
00507         {
00508           _DBUS_ASSERT_ERROR_IS_SET(error);
00509           return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
00510         }
00511     }
00512   else
00513     {
00514       _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00515       return DBUS_SERVER_LISTEN_NOT_HANDLED;
00516     }
00517 }
00518 
00528 void
00529 _dbus_server_socket_own_filename (DBusServer *server,
00530                                   char       *filename)
00531 {
00532   DBusServerSocket *socket_server = (DBusServerSocket*) server;
00533 
00534   socket_server->socket_name = filename;
00535 }
00536 
00537 

Generated on Thu Jan 22 16:37:05 2009 for D-Bus by  doxygen 1.5.1