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

dbus-server-unix.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-server-unix.c Server implementation for Unix network protocols.
00003  *
00004  * Copyright (C) 2002, 2003, 2004  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-unix.h"
00026 #include "dbus-transport-unix.h"
00027 #include "dbus-connection-internal.h"
00028 #include "dbus-string.h"
00029 #include <sys/types.h>
00030 #include <unistd.h>
00031 
00043 typedef struct DBusServerUnix DBusServerUnix;
00044 
00049 struct DBusServerUnix
00050 {
00051   DBusServer base;   
00052   int fd;            
00053   DBusWatch *watch;  
00054   char *socket_name; 
00055 };
00056 
00057 static void
00058 unix_finalize (DBusServer *server)
00059 {
00060   DBusServerUnix *unix_server = (DBusServerUnix*) server;
00061   
00062   _dbus_server_finalize_base (server);
00063 
00064   dbus_free (unix_server->socket_name);
00065   dbus_free (server);
00066 }
00067 
00073 /* Return value is just for memory, not other failures. */
00074 static dbus_bool_t
00075 handle_new_client_fd_and_unlock (DBusServer *server,
00076                                  int         client_fd)
00077 {
00078   DBusConnection *connection;
00079   DBusTransport *transport;
00080   DBusNewConnectionFunction new_connection_function;
00081   void *new_connection_data;
00082   
00083   _dbus_verbose ("Creating new client connection with fd %d\n", client_fd);
00084 
00085   HAVE_LOCK_CHECK (server);
00086   
00087   if (!_dbus_set_fd_nonblocking (client_fd, NULL))
00088     {
00089       SERVER_UNLOCK (server);
00090       return TRUE;
00091     }
00092   
00093   transport = _dbus_transport_new_for_fd (client_fd, TRUE, NULL);
00094   if (transport == NULL)
00095     {
00096       close (client_fd);
00097       SERVER_UNLOCK (server);
00098       return FALSE;
00099     }
00100 
00101   if (!_dbus_transport_set_auth_mechanisms (transport,
00102                                             (const char **) server->auth_mechanisms))
00103     {
00104       _dbus_transport_unref (transport);
00105       SERVER_UNLOCK (server);
00106       return FALSE;
00107     }
00108   
00109   /* note that client_fd is now owned by the transport, and will be
00110    * closed on transport disconnection/finalization
00111    */
00112   
00113   connection = _dbus_connection_new_for_transport (transport);
00114   _dbus_transport_unref (transport);
00115   transport = NULL; /* now under the connection lock */
00116   
00117   if (connection == NULL)
00118     {
00119       SERVER_UNLOCK (server);
00120       return FALSE;
00121     }
00122   
00123   /* See if someone wants to handle this new connection, self-referencing
00124    * for paranoia.
00125    */
00126   new_connection_function = server->new_connection_function;
00127   new_connection_data = server->new_connection_data;
00128 
00129   _dbus_server_ref_unlocked (server);
00130   SERVER_UNLOCK (server);
00131   
00132   if (new_connection_function)
00133     {
00134       (* new_connection_function) (server, connection,
00135                                    new_connection_data);
00136       dbus_server_unref (server);
00137     }
00138   
00139   /* If no one grabbed a reference, the connection will die. */
00140   dbus_connection_unref (connection);
00141 
00142   return TRUE;
00143 }
00144 
00145 static dbus_bool_t
00146 unix_handle_watch (DBusWatch    *watch,
00147                    unsigned int  flags,
00148                    void         *data)
00149 {
00150   DBusServer *server = data;
00151   DBusServerUnix *unix_server = data;
00152 
00153   SERVER_LOCK (server);
00154   
00155   _dbus_assert (watch == unix_server->watch);
00156 
00157   _dbus_verbose ("Handling client connection, flags 0x%x\n", flags);
00158   
00159   if (flags & DBUS_WATCH_READABLE)
00160     {
00161       int client_fd;
00162       int listen_fd;
00163       
00164       listen_fd = dbus_watch_get_fd (watch);
00165 
00166       client_fd = _dbus_accept (listen_fd);
00167       
00168       if (client_fd < 0)
00169         {
00170           /* EINTR handled for us */
00171           
00172           if (errno == EAGAIN || errno == EWOULDBLOCK)
00173             _dbus_verbose ("No client available to accept after all\n");
00174           else
00175             _dbus_verbose ("Failed to accept a client connection: %s\n",
00176                            _dbus_strerror (errno));
00177 
00178           SERVER_UNLOCK (server);
00179         }
00180       else
00181         {
00182           _dbus_fd_set_close_on_exec (client_fd);         
00183 
00184           if (!handle_new_client_fd_and_unlock (server, client_fd))
00185             _dbus_verbose ("Rejected client connection due to lack of memory\n");
00186         }
00187     }
00188 
00189   if (flags & DBUS_WATCH_ERROR)
00190     _dbus_verbose ("Error on server listening socket\n");
00191 
00192   if (flags & DBUS_WATCH_HANGUP)
00193     _dbus_verbose ("Hangup on server listening socket\n");
00194 
00195   return TRUE;
00196 }
00197   
00198 static void
00199 unix_disconnect (DBusServer *server)
00200 {
00201   DBusServerUnix *unix_server = (DBusServerUnix*) server;
00202 
00203   if (unix_server->watch)
00204     {
00205       _dbus_server_remove_watch (server,
00206                                  unix_server->watch);
00207       _dbus_watch_unref (unix_server->watch);
00208       unix_server->watch = NULL;
00209     }
00210   
00211   close (unix_server->fd);
00212   unix_server->fd = -1;
00213 
00214   if (unix_server->socket_name != NULL)
00215     {
00216       DBusString tmp;
00217       _dbus_string_init_const (&tmp, unix_server->socket_name);
00218       _dbus_delete_file (&tmp, NULL);
00219     }
00220 }
00221 
00222 static DBusServerVTable unix_vtable = {
00223   unix_finalize,
00224   unix_disconnect
00225 };
00226 
00240 DBusServer*
00241 _dbus_server_new_for_fd (int               fd,
00242                          const DBusString *address)
00243 {
00244   DBusServerUnix *unix_server;
00245   DBusWatch *watch;
00246   
00247   unix_server = dbus_new0 (DBusServerUnix, 1);
00248   if (unix_server == NULL)
00249     return NULL;
00250 
00251   watch = _dbus_watch_new (fd,
00252                            DBUS_WATCH_READABLE,
00253                            TRUE,
00254                            unix_handle_watch, unix_server,
00255                            NULL);
00256   if (watch == NULL)
00257     {
00258       dbus_free (unix_server);
00259       return NULL;
00260     }
00261   
00262   if (!_dbus_server_init_base (&unix_server->base,
00263                                &unix_vtable, address))
00264     {
00265       _dbus_watch_unref (watch);
00266       dbus_free (unix_server);
00267       return NULL;
00268     }
00269 
00270 #ifndef DBUS_DISABLE_CHECKS
00271   unix_server->base.have_server_lock = TRUE;
00272 #endif
00273   
00274   if (!_dbus_server_add_watch (&unix_server->base,
00275                                watch))
00276     {
00277       _dbus_server_finalize_base (&unix_server->base);
00278       _dbus_watch_unref (watch);
00279       dbus_free (unix_server);
00280       return NULL;
00281     }
00282 
00283 #ifndef DBUS_DISABLE_CHECKS
00284   unix_server->base.have_server_lock = FALSE;
00285 #endif
00286   
00287   unix_server->fd = fd;
00288   unix_server->watch = watch;
00289 
00290   return (DBusServer*) unix_server;
00291 }
00292 
00301 DBusServer*
00302 _dbus_server_new_for_domain_socket (const char     *path,
00303                                     dbus_bool_t     abstract,
00304                                     DBusError      *error)
00305 {
00306   DBusServer *server;
00307   DBusServerUnix *unix_server;
00308   int listen_fd;
00309   DBusString address;
00310   char *path_copy;
00311   
00312   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00313 
00314   if (!_dbus_string_init (&address))
00315     {
00316       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00317       return NULL;
00318     }
00319 
00320   if ((abstract &&
00321        !_dbus_string_append (&address, "unix:abstract=")) ||
00322       (!abstract &&
00323        !_dbus_string_append (&address, "unix:path=")) ||
00324       !_dbus_string_append (&address, path))
00325     {
00326       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00327       goto failed_0;
00328     }
00329 
00330   path_copy = _dbus_strdup (path);
00331   if (path_copy == NULL)
00332     {
00333       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00334       goto failed_0;
00335     }
00336   
00337   listen_fd = _dbus_listen_unix_socket (path, abstract, error);
00338   _dbus_fd_set_close_on_exec (listen_fd);
00339   
00340   if (listen_fd < 0)
00341     {
00342       _DBUS_ASSERT_ERROR_IS_SET (error);
00343       goto failed_1;
00344     }
00345   
00346   server = _dbus_server_new_for_fd (listen_fd, &address);
00347   if (server == NULL)
00348     {
00349       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00350       goto failed_2;
00351     }
00352 
00353   unix_server = (DBusServerUnix*) server;
00354   unix_server->socket_name = path_copy;
00355   
00356   _dbus_string_free (&address);
00357   
00358   return server;
00359 
00360  failed_2:
00361   _dbus_close (listen_fd, NULL);
00362  failed_1:
00363   dbus_free (path_copy);
00364  failed_0:
00365   _dbus_string_free (&address);
00366 
00367   return NULL;
00368 }
00369 
00379 DBusServer*
00380 _dbus_server_new_for_tcp_socket (const char     *host,
00381                                  dbus_uint32_t   port,
00382                                  DBusError      *error)
00383 {
00384   DBusServer *server;
00385   int listen_fd;
00386   DBusString address;
00387   
00388   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00389 
00390   if (!_dbus_string_init (&address))
00391     {
00392       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00393       return NULL;
00394     }
00395 
00396   if (host == NULL)
00397     host = "localhost";
00398 
00399   if (!_dbus_string_append (&address, "tcp:host=") ||
00400       !_dbus_string_append (&address, host) ||
00401       !_dbus_string_append (&address, ",port=") ||
00402       !_dbus_string_append_int (&address, port))
00403     {
00404       _dbus_string_free (&address);
00405       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00406       return NULL;
00407     }
00408   
00409   listen_fd = _dbus_listen_tcp_socket (host, port, error);
00410   _dbus_fd_set_close_on_exec (listen_fd);
00411   
00412   if (listen_fd < 0)
00413     {
00414       _dbus_string_free (&address);
00415       return NULL;
00416     }
00417   
00418   server = _dbus_server_new_for_fd (listen_fd, &address);
00419   if (server == NULL)
00420     {
00421       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00422       close (listen_fd);
00423       _dbus_string_free (&address);
00424       return NULL;
00425     }
00426 
00427   _dbus_string_free (&address);
00428   
00429   return server;
00430 
00431 
00432 }
00433 

Generated on Wed Mar 30 21:15:22 2005 for D-BUS by  doxygen 1.4.1