2003-01-27 Anders Carlsson <andersca@codefactory.se>
[platform/upstream/dbus.git] / bus / dispatch.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dispatch.c  Message dispatcher
3  *
4  * Copyright (C) 2003  CodeFactory AB
5  *
6  * Licensed under the Academic Free License version 1.2
7  * 
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  * 
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23
24 #include "dispatch.h"
25 #include "connection.h"
26 #include "driver.h"
27 #include <dbus/dbus-internals.h>
28 #include <string.h>
29
30 static int message_handler_slot;
31
32 static void
33 send_one_message (DBusConnection *connection, void *data)
34 {
35   _DBUS_HANDLE_OOM (dbus_connection_send_message (connection, data, NULL, NULL));
36 }
37
38 void
39 bus_dispatch_broadcast_message (DBusMessage *message)
40 {
41   _dbus_assert (dbus_message_get_sender (message) != NULL);
42   
43   bus_connection_foreach (send_one_message, message);
44   
45 }
46
47 static DBusHandlerResult
48 bus_dispatch_message_handler (DBusMessageHandler *handler,
49                               DBusConnection     *connection,
50                               DBusMessage        *message,
51                               void               *user_data)
52 {
53   const char *sender, *service_name;
54   
55   /* Assign a sender to the message */
56   sender = bus_connection_get_name (connection);
57   _DBUS_HANDLE_OOM (dbus_message_set_sender (message, sender));
58
59   service_name = dbus_message_get_service (message);
60   
61   /* See if the message is to the driver */
62   if (strcmp (service_name, DBUS_SERVICE_DBUS) == 0)
63     {
64       bus_driver_handle_message (connection, message);
65     }
66   else if (sender == NULL)
67     {
68       _dbus_verbose ("Received message from non-registered client. Disconnecting.\n");
69       dbus_connection_disconnect (connection);
70     }
71   else if (strcmp (service_name, DBUS_SERVICE_BROADCAST) == 0)
72     {
73       bus_dispatch_broadcast_message (message);
74     }
75   else  
76     {
77       DBusString service_string;
78       BusService *service;
79
80       _dbus_string_init_const (&service_string, service_name);
81       service = bus_service_lookup (&service_string, FALSE);
82
83       _dbus_assert (bus_service_get_primary_owner (service) != NULL);
84       
85       /* Dispatch the message */
86       _DBUS_HANDLE_OOM (dbus_connection_send_message (bus_service_get_primary_owner (service),
87                                                       message, NULL, NULL));
88     }
89
90   return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
91 }
92
93 dbus_bool_t
94 bus_dispatch_add_connection (DBusConnection *connection)
95 {
96   DBusMessageHandler *handler;
97   
98   message_handler_slot = dbus_connection_allocate_data_slot ();
99
100   if (message_handler_slot < 0)
101     return FALSE;
102
103   handler = dbus_message_handler_new (bus_dispatch_message_handler, NULL, NULL);  
104
105   if (!dbus_connection_add_filter (connection, handler))
106     {
107       dbus_message_handler_unref (handler);
108
109       return FALSE;
110     }
111
112   if (!dbus_connection_set_data (connection,
113                                  message_handler_slot,
114                                  handler,
115                                  (DBusFreeFunction)dbus_message_handler_unref))
116     {
117       dbus_connection_remove_filter (connection, handler);
118       dbus_message_handler_unref (handler);
119
120       return FALSE;
121     }
122
123   return TRUE;
124 }
125
126 void
127 bus_dispatch_remove_connection (DBusConnection *connection)
128 {
129   /* Here we tell the bus driver that we want to get off. */
130   bus_driver_remove_connection (connection);
131
132   dbus_connection_set_data (connection,
133                             message_handler_slot,
134                             NULL, NULL);
135 }
136