lib: fixes to library
[platform/core/appfw/message-port-dbus.git] / lib / msgport-manager.c
1 #include "msgport-manager.h"
2 #include "msgport-service.h"
3 #include "msgport-utils.h" /* msgport_daemon_error_to_error */
4 #include "message-port.h" /* messageport_error_e */
5 #include "common/dbus-manager-glue.h"
6 #include "common/log.h"
7 #include "config.h" /* MESSAGEPORT_BUS_ADDRESS */
8 #include <gio/gio.h>
9
10 struct _MsgPortManager
11 {
12     GObject parent;
13
14     MsgPortDbusGlueManager *proxy;
15     GHashTable *services; /* {gchar*:MsgPortService*} */
16     GHashTable *local_services; /* {gint: gchar *} */ 
17     GHashTable *remote_services; /* {gint: gchar *} */
18 };
19
20 G_DEFINE_TYPE (MsgPortManager, msgport_manager, G_TYPE_OBJECT)
21
22 static void
23 _unregister_service_cb (int service_id, const gchar *object_path, MsgPortManager *manager)
24 {
25     MsgPortService *service = g_hash_table_lookup (manager->services, object_path);
26
27     if (service) msgport_service_unregister (service);
28 }
29
30 static void
31 _finalize (GObject *self)
32 {
33     MsgPortManager *manager = MSGPORT_MANAGER (self);
34
35     if (manager->local_services) {
36         g_hash_table_unref (manager->local_services);
37         manager->local_services = NULL;
38     }
39
40     if (manager->remote_services) {
41         g_hash_table_unref (manager->remote_services);
42         manager->remote_services = NULL;
43     }
44
45     G_OBJECT_CLASS (msgport_manager_parent_class)->finalize (self);
46 }
47
48 static void
49 _dispose (GObject *self)
50 {
51     MsgPortManager *manager = MSGPORT_MANAGER (self);
52
53     g_hash_table_foreach (manager->local_services, (GHFunc)_unregister_service_cb, manager);
54
55     if (manager->services) {
56         g_hash_table_unref (manager->services);
57         manager->services = NULL;
58     }
59
60     g_clear_object (&manager->proxy);
61
62     G_OBJECT_CLASS (msgport_manager_parent_class)->dispose (self);
63 }
64
65 static void
66 msgport_manager_class_init (MsgPortManagerClass *klass)
67 {
68     GObjectClass *g_klass = G_OBJECT_CLASS (klass);
69
70     g_klass->finalize = _finalize;
71     g_klass->dispose = _dispose;
72 }
73
74 static void
75 msgport_manager_init (MsgPortManager *manager)
76 {
77     GError          *error = NULL;
78     GDBusConnection *connection = NULL;
79     gchar           *bus_address = g_strdup_printf (MESSAGEPORT_BUS_ADDRESS);
80
81     manager->services = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
82     manager->local_services = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
83     manager->remote_services = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
84
85     connection = g_dbus_connection_new_for_address_sync (bus_address,
86             G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, NULL, NULL, &error);
87     if (error) {
88         WARN ("Fail to connect messageport server at address %s: %s", bus_address, error->message);
89         g_error_free (error);
90     }
91     else {
92         manager->proxy = msgport_dbus_glue_manager_proxy_new_sync (
93             connection, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL, "/", NULL, &error);
94         if (error) {
95             WARN ("Fail to get manager proxy : %s", error->message);
96             g_error_free (error);
97         }
98     }
99 }
100
101 MsgPortManager * msgport_manager_new ()
102 {
103     return g_object_new (MSGPORT_TYPE_MANAGER, NULL);
104 }
105
106 static MsgPortManager *__manager;
107
108 MsgPortManager * msgport_get_manager () 
109 {
110     if (!__manager) {
111         __manager = msgport_manager_new ();
112     }
113
114     return __manager;
115 }
116
117 static messageport_error_e
118 _create_and_cache_service (MsgPortManager *manager, gchar *object_path, messageport_message_cb cb, int *service_id)
119 {
120     int id;
121     MsgPortService *service = msgport_service_new (
122             g_dbus_proxy_get_connection (G_DBUS_PROXY(manager->proxy)),
123             object_path, cb);
124     if (!service) {
125         g_free (object_path);
126         return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
127     }
128
129     id = msgport_service_id (service);
130
131     g_hash_table_insert (manager->services, object_path, service);
132     g_hash_table_insert (manager->local_services, GINT_TO_POINTER (id), object_path);
133
134     if (service_id) *service_id = id;
135
136     return MESSAGEPORT_ERROR_NONE;
137 }
138
139 messageport_error_e
140 msgport_manager_register_service (MsgPortManager *manager, const gchar *port_name, gboolean is_trusted, messageport_message_cb message_cb, int *service_id)
141 {
142     GError *error = NULL;
143     gchar *object_path = NULL;
144
145     g_return_val_if_fail (manager && MSGPORT_IS_MANAGER (manager), MESSAGEPORT_ERROR_IO_ERROR);
146     g_return_val_if_fail (manager->proxy, MESSAGEPORT_ERROR_IO_ERROR);
147     g_return_val_if_fail (service_id && port_name && message_cb, MESSAGEPORT_ERROR_INVALID_PARAMETER);
148
149     msgport_dbus_glue_manager_call_register_service_sync (manager->proxy,
150             port_name, is_trusted, &object_path, NULL, &error);
151
152     if (error) {
153         messageport_error_e err = msgport_daemon_error_to_error (error);
154         WARN ("unable to register service (%s): %s", port_name, error->message);
155         g_error_free (error);
156         return err; 
157     }
158
159     return _create_and_cache_service (manager, object_path, message_cb, service_id);
160 }
161
162 static MsgPortService *
163 _get_local_port (MsgPortManager *manager, int service_id)
164 {
165     const gchar *object_path = NULL;
166     MsgPortService *service = NULL;
167
168     object_path = g_hash_table_lookup (manager->local_services, GINT_TO_POINTER(service_id));
169     if (!object_path) return NULL;
170
171     service = MSGPORT_SERVICE (g_hash_table_lookup (manager->services, object_path));
172     if (!service) {
173         g_hash_table_remove (manager->local_services, GINT_TO_POINTER (service_id));
174         return NULL;
175     }
176
177     return service;
178 }
179
180 messageport_error_e
181 msgport_manager_unregister_servcie (MsgPortManager *manager, int service_id)
182 {
183     const gchar *object_path = NULL;
184     MsgPortService *service = NULL;
185     g_return_val_if_fail (manager && MSGPORT_IS_MANAGER (manager), FALSE);
186     g_return_val_if_fail (manager->proxy, MESSAGEPORT_ERROR_IO_ERROR);
187
188     service = _get_local_port (manager, service_id);
189     if (!service) {
190         WARN ("No local service found for service id '%d'", service_id);
191         return MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
192     }
193
194     if (!msgport_service_unregister (service)) 
195         return MESSAGEPORT_ERROR_IO_ERROR;
196
197     object_path = (const gchar *)g_hash_table_lookup (manager->local_services,
198                                                       GINT_TO_POINTER(service_id));
199     g_hash_table_remove (manager->local_services, GINT_TO_POINTER(service_id));
200     g_hash_table_remove (manager->services, object_path);
201
202     return MESSAGEPORT_ERROR_NONE;
203 }
204
205 messageport_error_e 
206 msgport_manager_check_remote_service (MsgPortManager *manager, const gchar *app_id, const gchar *port, gboolean is_trusted, guint *service_id_out)
207 {
208     GError *error = NULL;
209     guint remote_service_id = 0;
210
211     if (service_id_out) *service_id_out = 0;
212
213     g_return_val_if_fail (manager && MSGPORT_IS_MANAGER (manager), MESSAGEPORT_ERROR_IO_ERROR);
214     g_return_val_if_fail (manager->proxy, MESSAGEPORT_ERROR_IO_ERROR);
215     g_return_val_if_fail (app_id && port, MESSAGEPORT_ERROR_INVALID_PARAMETER);
216
217     if (!app_id || !port) return MESSAGEPORT_ERROR_INVALID_PARAMETER;
218
219     msgport_dbus_glue_manager_call_check_for_remote_service_sync (manager->proxy,
220             app_id, port, is_trusted, &remote_service_id, NULL, &error);
221
222     if (error) {
223         messageport_error_e err = msgport_daemon_error_to_error (error);
224         WARN ("No %sservice found for app_id %s, port name %s: %s", 
225                 is_trusted ? "trusted " : "", app_id, port, error->message);
226         g_error_free (error);
227         return err;
228     }
229     else {
230         DBG ("Got service id %d for %s, %s", remote_service_id, app_id, port);
231         if (service_id_out)  *service_id_out = remote_service_id;
232     }
233
234     return MESSAGEPORT_ERROR_NONE;
235 }
236
237 messageport_error_e
238 msgport_manager_get_service_name (MsgPortManager *manager, int service_id, gchar **name_out)
239 {
240     MsgPortService *service = NULL;
241     g_return_val_if_fail (manager && MSGPORT_IS_MANAGER (manager), MESSAGEPORT_ERROR_IO_ERROR);
242     g_return_val_if_fail (manager->proxy, MESSAGEPORT_ERROR_IO_ERROR);
243     g_return_val_if_fail (name_out && service_id, MESSAGEPORT_ERROR_INVALID_PARAMETER);
244
245     service = _get_local_port (manager, service_id);
246     if (!service) return MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
247
248     *name_out = g_strdup (msgport_service_name (service));
249     DBG ("PORT NAME : %s", *name_out);
250
251     return MESSAGEPORT_ERROR_NONE;
252 }
253
254 messageport_error_e
255 msgport_manager_send_message (MsgPortManager *manager, const gchar *remote_app_id, const gchar *remote_port, gboolean is_trusted, GVariant *data)
256 {
257     guint service_id = 0;
258     GError *error = NULL;
259     messageport_error_e err;
260
261     g_return_val_if_fail (manager && MSGPORT_IS_MANAGER (manager), MESSAGEPORT_ERROR_IO_ERROR);
262     g_return_val_if_fail (manager->proxy, MESSAGEPORT_ERROR_IO_ERROR);
263     g_return_val_if_fail (remote_app_id && remote_port, MESSAGEPORT_ERROR_INVALID_PARAMETER);
264
265     err = msgport_manager_check_remote_service (manager, remote_app_id, remote_port, is_trusted, &service_id);
266     if (service_id == 0) return err;
267
268     msgport_dbus_glue_manager_call_send_message_sync (manager->proxy, service_id, data, NULL, &error);
269
270     if (error) {
271         err = msgport_daemon_error_to_error (error);
272         WARN ("Failed to send message to (%s:%s) : %s", remote_app_id, remote_port, error->message);
273         g_error_free (error);
274         return err;
275     }
276
277     return MESSAGEPORT_ERROR_NONE;
278 }
279
280 messageport_error_e
281 msgport_manager_send_bidirectional_message (MsgPortManager *manager, int local_port_id, const gchar *remote_app_id, const gchar *remote_port, gboolean is_trusted, GVariant *data)
282 {
283     MsgPortService *service = NULL;
284     guint remote_service_id = 0;
285     messageport_error_e res = 0;
286
287     g_return_val_if_fail (manager && MSGPORT_IS_MANAGER (manager), MESSAGEPORT_ERROR_IO_ERROR);
288     g_return_val_if_fail (manager->proxy, MESSAGEPORT_ERROR_IO_ERROR);
289     g_return_val_if_fail (local_port_id > 0 && remote_app_id && remote_port, MESSAGEPORT_ERROR_INVALID_PARAMETER);
290
291     service = _get_local_port (manager, local_port_id);
292     if (!service) {
293         WARN ("No local service found for service id '%d'", local_port_id);
294         return MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
295     }
296
297     if ((res = msgport_manager_check_remote_service (manager, remote_app_id, remote_port, is_trusted, &remote_service_id) != MESSAGEPORT_ERROR_NONE)) {
298         WARN ("No remote %sport informatuon for %s:%s, error : %d", is_trusted ? "trusted " : "", remote_app_id, remote_port, res);
299         return MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
300     }
301
302     DBG ("Sending message from local service '%p' to remote sercie id '%d'", service, remote_service_id);
303     return msgport_service_send_message (service, remote_service_id, data);
304 }
305