Main Page   Modules   Data Structures   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  Red Hat Inc.
00005  *
00006  * Licensed under the Academic Free License version 1.2
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 <sys/types.h>
00029 #include <unistd.h>
00030 
00042 typedef struct DBusServerUnix DBusServerUnix;
00043 
00048 struct DBusServerUnix
00049 {
00050   DBusServer base;   
00051   int fd;            
00052   DBusWatch *watch;  
00053   char *socket_name; 
00054 };
00055 
00056 static void
00057 unix_finalize (DBusServer *server)
00058 {
00059   DBusServerUnix *unix_server = (DBusServerUnix*) server;
00060 
00061   if (unix_server->watch)
00062     _dbus_watch_unref (unix_server->watch);
00063 
00064   dbus_free (unix_server->socket_name);
00065   
00066   _dbus_server_finalize_base (server);
00067   
00068   dbus_free (server);
00069 }
00070 
00076 /* Return value is just for memory, not other failures. */
00077 static dbus_bool_t
00078 handle_new_client_fd (DBusServer *server,
00079                       int         client_fd)
00080 {
00081   DBusConnection *connection;
00082   DBusTransport *transport;
00083   
00084   _dbus_verbose ("Creating new client connection with fd %d\n", client_fd);
00085           
00086   if (!_dbus_set_fd_nonblocking (client_fd, NULL))
00087     return TRUE;
00088   
00089   transport = _dbus_transport_new_for_fd (client_fd, TRUE, NULL);
00090   if (transport == NULL)
00091     {
00092       close (client_fd);
00093       return FALSE;
00094     }
00095 
00096   if (!_dbus_transport_set_auth_mechanisms (transport,
00097                                             (const char **) server->auth_mechanisms))
00098     {
00099       _dbus_transport_unref (transport);
00100       return FALSE;
00101     }
00102   
00103   /* note that client_fd is now owned by the transport, and will be
00104    * closed on transport disconnection/finalization
00105    */
00106   
00107   connection = _dbus_connection_new_for_transport (transport);
00108   _dbus_transport_unref (transport);
00109   
00110   if (connection == NULL)
00111     return FALSE;
00112   
00113   /* See if someone wants to handle this new connection,
00114    * self-referencing for paranoia
00115    */
00116   if (server->new_connection_function)
00117     {
00118       dbus_server_ref (server);
00119       
00120       (* server->new_connection_function) (server, connection,
00121                                            server->new_connection_data);
00122       dbus_server_unref (server);
00123     }
00124   
00125   /* If no one grabbed a reference, the connection will die. */
00126   dbus_connection_unref (connection);
00127 
00128   return TRUE;
00129 }
00130 
00131 static dbus_bool_t
00132 unix_handle_watch (DBusWatch    *watch,
00133                    unsigned int  flags,
00134                    void         *data)
00135 {
00136   DBusServer *server = data;
00137   DBusServerUnix *unix_server = data;
00138 
00139   _dbus_assert (watch == unix_server->watch);
00140 
00141   _dbus_verbose ("Handling client connection, flags 0x%x\n", flags);
00142   
00143   if (flags & DBUS_WATCH_READABLE)
00144     {
00145       int client_fd;
00146       int listen_fd;
00147       
00148       listen_fd = dbus_watch_get_fd (watch);
00149 
00150       client_fd = _dbus_accept (listen_fd);
00151       
00152       if (client_fd < 0)
00153         {
00154           /* EINTR handled for us */
00155           
00156           if (errno == EAGAIN || errno == EWOULDBLOCK)
00157             _dbus_verbose ("No client available to accept after all\n");
00158           else
00159             _dbus_verbose ("Failed to accept a client connection: %s\n",
00160                            _dbus_strerror (errno));
00161         }
00162       else
00163         {
00164           _dbus_fd_set_close_on_exec (client_fd);         
00165 
00166           if (!handle_new_client_fd (server, client_fd))
00167             _dbus_verbose ("Rejected client connection due to lack of memory\n");
00168         }
00169     }
00170 
00171   if (flags & DBUS_WATCH_ERROR)
00172     _dbus_verbose ("Error on server listening socket\n");
00173 
00174   if (flags & DBUS_WATCH_HANGUP)
00175     _dbus_verbose ("Hangup on server listening socket\n");
00176 
00177   return TRUE;
00178 }
00179   
00180 static void
00181 unix_disconnect (DBusServer *server)
00182 {
00183   DBusServerUnix *unix_server = (DBusServerUnix*) server;
00184 
00185   if (unix_server->watch)
00186     {
00187       _dbus_server_remove_watch (server,
00188                                  unix_server->watch);
00189       _dbus_watch_unref (unix_server->watch);
00190       unix_server->watch = NULL;
00191     }
00192   
00193   close (unix_server->fd);
00194   unix_server->fd = -1;
00195 
00196   if (unix_server->socket_name != NULL)
00197     {
00198       DBusString tmp;
00199       _dbus_string_init_const (&tmp, unix_server->socket_name);
00200       _dbus_delete_file (&tmp, NULL);
00201     }
00202 }
00203 
00204 static DBusServerVTable unix_vtable = {
00205   unix_finalize,
00206   unix_disconnect
00207 };
00208 
00222 DBusServer*
00223 _dbus_server_new_for_fd (int               fd,
00224                          const DBusString *address)
00225 {
00226   DBusServerUnix *unix_server;
00227   DBusWatch *watch;
00228   
00229   unix_server = dbus_new0 (DBusServerUnix, 1);
00230   if (unix_server == NULL)
00231     return NULL;
00232 
00233   watch = _dbus_watch_new (fd,
00234                            DBUS_WATCH_READABLE,
00235                            TRUE,
00236                            unix_handle_watch, unix_server,
00237                            NULL);
00238   if (watch == NULL)
00239     {
00240       dbus_free (unix_server);
00241       return NULL;
00242     }
00243   
00244   if (!_dbus_server_init_base (&unix_server->base,
00245                                &unix_vtable, address))
00246     {
00247       _dbus_watch_unref (watch);
00248       dbus_free (unix_server);
00249       return NULL;
00250     }
00251 
00252   if (!_dbus_server_add_watch (&unix_server->base,
00253                                watch))
00254     {
00255       _dbus_server_finalize_base (&unix_server->base);
00256       _dbus_watch_unref (watch);
00257       dbus_free (unix_server);
00258       return NULL;
00259     }
00260   
00261   unix_server->fd = fd;
00262   unix_server->watch = watch;
00263 
00264   return (DBusServer*) unix_server;
00265 }
00266 
00275 DBusServer*
00276 _dbus_server_new_for_domain_socket (const char     *path,
00277                                     dbus_bool_t     abstract,
00278                                     DBusError      *error)
00279 {
00280   DBusServer *server;
00281   DBusServerUnix *unix_server;
00282   int listen_fd;
00283   DBusString address;
00284   char *path_copy;
00285   
00286   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00287 
00288   if (!_dbus_string_init (&address))
00289     {
00290       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00291       return NULL;
00292     }
00293 
00294   if ((abstract &&
00295        !_dbus_string_append (&address, "unix:abstract=")) ||
00296       (!abstract &&
00297        !_dbus_string_append (&address, "unix:path=")) ||
00298       !_dbus_string_append (&address, path))
00299     {
00300       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00301       goto failed_0;
00302     }
00303 
00304   path_copy = _dbus_strdup (path);
00305   if (path_copy == NULL)
00306     {
00307       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00308       goto failed_0;
00309     }
00310   
00311   listen_fd = _dbus_listen_unix_socket (path, abstract, error);
00312   _dbus_fd_set_close_on_exec (listen_fd);
00313   
00314   if (listen_fd < 0)
00315     {
00316       _DBUS_ASSERT_ERROR_IS_SET (error);
00317       goto failed_1;
00318     }
00319   
00320   server = _dbus_server_new_for_fd (listen_fd, &address);
00321   if (server == NULL)
00322     {
00323       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00324       goto failed_2;
00325     }
00326 
00327   unix_server = (DBusServerUnix*) server;
00328   unix_server->socket_name = path_copy;
00329   
00330   _dbus_string_free (&address);
00331   
00332   return server;
00333 
00334  failed_2:
00335   _dbus_close (listen_fd, NULL);
00336  failed_1:
00337   dbus_free (path_copy);
00338  failed_0:
00339   _dbus_string_free (&address);
00340 
00341   return NULL;
00342 }
00343 
00353 DBusServer*
00354 _dbus_server_new_for_tcp_socket (const char     *host,
00355                                  dbus_uint32_t   port,
00356                                  DBusError      *error)
00357 {
00358   DBusServer *server;
00359   int listen_fd;
00360   DBusString address;
00361   
00362   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00363 
00364   if (!_dbus_string_init (&address))
00365     {
00366       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00367       return NULL;
00368     }
00369 
00370   if (!_dbus_string_append (&address, "tcp:host=") ||
00371       !_dbus_string_append (&address, host) ||
00372       !_dbus_string_append (&address, ",port=") ||
00373       !_dbus_string_append_int (&address, port))
00374     {
00375       _dbus_string_free (&address);
00376       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00377       return NULL;
00378     }
00379   
00380   listen_fd = _dbus_listen_tcp_socket (host, port, error);
00381   _dbus_fd_set_close_on_exec (listen_fd);
00382   
00383   if (listen_fd < 0)
00384     {
00385       _dbus_string_free (&address);
00386       return NULL;
00387     }
00388   
00389   server = _dbus_server_new_for_fd (listen_fd, &address);
00390   if (server == NULL)
00391     {
00392       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00393       close (listen_fd);
00394       _dbus_string_free (&address);
00395       return NULL;
00396     }
00397 
00398   _dbus_string_free (&address);
00399   
00400   return server;
00401 
00402 
00403 }
00404 

Generated on Wed Oct 22 14:05:03 2003 for D-BUS by doxygen1.3-rc3