459bfe506da35e5a8a4fcdb8955808c3b63b83e0
[platform/core/appfw/message-port.git] / src / message_port.c
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <glib.h>
18 #include <stdlib.h>
19 #include <stdbool.h>
20 #include <pthread.h>
21 #include <message-port.h>
22 #include "message_port_internal.h"
23 #include "message_port_log.h"
24 #include "message_port.h"
25
26 typedef struct message_port_callback_item_s {
27         message_port_message_cb callback;
28         void *user_data;
29 } message_port_callback_item;
30
31 static GHashTable *__listeners;
32 static GHashTable *__trusted_listeners;
33 static pthread_mutex_t __mutex = PTHREAD_MUTEX_INITIALIZER;
34
35 static void do_callback(message_port_message_cb callback, int local_port_id, const char *remote_app_id, const char *remote_port, bool trusted_remote_port, bundle *message, void *user_data)
36 {
37         if (callback)
38                 callback(local_port_id, remote_app_id, remote_port, trusted_remote_port, message, user_data);
39         else
40                 _LOGI("Ignored");
41 }
42
43 static void message_dispatcher(int local_port_id, const char *remote_app_id, const char *remote_port, bool trusted_remote_port, bundle *message, void *user_data)
44 {
45         message_port_callback_item *item = NULL;
46         if (__listeners == NULL)
47                 return;
48         item = (message_port_callback_item *)g_hash_table_lookup(__listeners, GINT_TO_POINTER(local_port_id));
49         if (item != NULL)
50                 do_callback(item->callback, local_port_id, remote_app_id, remote_port, trusted_remote_port, message, item->user_data);
51 }
52
53 static void trusted_message_dispatcher(int trusted_local_port_id, const char *remote_app_id, const char *remote_port, bool trusted_remote_port, bundle *message, void *user_data)
54 {
55         message_port_callback_item *item = NULL;
56
57         if (__trusted_listeners == NULL)
58                 return;
59         item = (message_port_callback_item *)g_hash_table_lookup(__trusted_listeners, GINT_TO_POINTER(trusted_local_port_id));
60         if (item != NULL)
61                 do_callback(item->callback, trusted_local_port_id, remote_app_id, remote_port, trusted_remote_port, message, item->user_data);
62 }
63
64 int message_port_register_local_port(const char *local_port, message_port_message_cb callback, void *user_data)
65 {
66         if (local_port == NULL || callback == NULL) {
67                 _LOGE("[MESSAGE_PORT_ERROR_INVALID_PARAMETER] NULL value is not allowed.");
68                 return MESSAGE_PORT_ERROR_INVALID_PARAMETER;
69         }
70
71         int local_port_id = messageport_register_local_port(local_port, message_dispatcher);
72         if (local_port_id > 0) {
73                 _SECURE_LOGI("Register local port ID (%d).", local_port_id);
74
75                 if (__listeners == NULL)
76                         __listeners = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
77
78                 pthread_mutex_lock(&__mutex);
79                 message_port_callback_item *item =
80                         (message_port_callback_item *)g_hash_table_lookup(__listeners, GINT_TO_POINTER(local_port_id));
81                 if (item == NULL) {
82                         item = (message_port_callback_item *)calloc(1, sizeof(message_port_callback_item));
83                         if (item == NULL) {
84                                 pthread_mutex_unlock(&__mutex);
85                                 return MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
86                         }
87
88                         g_hash_table_insert(__listeners, GINT_TO_POINTER(local_port_id), item);
89                 }
90
91                 item->callback = callback;
92                 item->user_data = user_data;
93                 pthread_mutex_unlock(&__mutex);
94
95         } else {
96                 _SECURE_LOGI("Register local port fail (%d).", local_port_id);
97         }
98
99         return convert_to_tizen_error((messageport_error_e)local_port_id);
100 }
101
102 int message_port_register_trusted_local_port(const char *local_port, message_port_trusted_message_cb callback, void *user_data)
103 {
104         if (local_port == NULL || callback == NULL) {
105                 _LOGE("[MESSAGE_PORT_ERROR_INVALID_PARAMETER] NULL value is not allowed.");
106                 return MESSAGE_PORT_ERROR_INVALID_PARAMETER;
107         }
108
109         int trusted_local_port_id = messageport_register_trusted_local_port(local_port, trusted_message_dispatcher);
110         if (trusted_local_port_id > 0) {
111                 _SECURE_LOGI("Register trusted local port ID (%d).", trusted_local_port_id);
112
113                 if (__trusted_listeners == NULL)
114                         __trusted_listeners = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
115
116                 pthread_mutex_lock(&__mutex);
117                 message_port_callback_item *item =
118                         (message_port_callback_item *)g_hash_table_lookup(__trusted_listeners, GINT_TO_POINTER(trusted_local_port_id));
119                 if (item == NULL) {
120                         item = (message_port_callback_item *)calloc(1, sizeof(message_port_callback_item));
121                         if (item == NULL) {
122                                 pthread_mutex_unlock(&__mutex);
123                                 return MESSAGE_PORT_ERROR_OUT_OF_MEMORY;
124                         }
125
126                         g_hash_table_insert(__trusted_listeners, GINT_TO_POINTER(trusted_local_port_id), item);
127                 }
128
129                 item->callback = callback;
130                 item->user_data = user_data;
131                 pthread_mutex_unlock(&__mutex);
132         } else {
133                 _SECURE_LOGI("Register trusted local port fail (%d).", trusted_local_port_id);
134         }
135
136         return convert_to_tizen_error((messageport_error_e)trusted_local_port_id);
137 }
138
139 int message_port_unregister_local_port(int local_port_id)
140 {
141         int res = MESSAGE_PORT_ERROR_NONE;
142         if (local_port_id <= 0) {
143                 _LOGE("[MESSAGEPORT_ERROR_INVALID_PARAMETER] Neither 0 nor negative value is allowed.");
144                 return MESSAGE_PORT_ERROR_INVALID_PARAMETER;
145         } else {
146                 res = messageport_unregister_local_port(local_port_id, false);
147                 g_hash_table_remove(__listeners, GINT_TO_POINTER(local_port_id));
148         }
149         return convert_to_tizen_error((messageport_error_e)res);
150 }
151
152 int message_port_unregister_trusted_local_port(int trusted_local_port_id)
153 {
154
155         int res = MESSAGE_PORT_ERROR_NONE;
156         if (trusted_local_port_id <= 0) {
157                 _LOGE("[MESSAGEPORT_ERROR_INVALID_PARAMETER] Neither 0 nor negative value is allowed.");
158                 return MESSAGE_PORT_ERROR_INVALID_PARAMETER;
159         } else {
160                 res = messageport_unregister_local_port(trusted_local_port_id, true);
161                 g_hash_table_remove(__trusted_listeners, GINT_TO_POINTER(trusted_local_port_id));
162         }
163
164         return convert_to_tizen_error((messageport_error_e)res);
165 }
166
167 int message_port_check_remote_port(const char *remote_app_id, const char *remote_port, bool *exist)
168 {
169         if (remote_app_id == NULL || remote_port == NULL) {
170                 _LOGE("[MESSAGE_PORT_ERROR_INVALID_PARAMETER] NULL value is not allowed.");
171                 return MESSAGE_PORT_ERROR_INVALID_PARAMETER;
172         }
173         _SECURE_LOGI("Check remote port (%s):(%s).", remote_app_id, remote_port);
174         return convert_to_tizen_error((messageport_error_e)messageport_check_remote_port(remote_app_id, remote_port, exist));
175 }
176
177 int message_port_check_trusted_remote_port(const char *remote_app_id, const char *remote_port, bool *exist)
178 {
179         if (remote_app_id == NULL || remote_port == NULL) {
180                 _LOGE("[MESSAGE_PORT_ERROR_INVALID_PARAMETER] NULL value is not allowed.");
181                 return MESSAGE_PORT_ERROR_INVALID_PARAMETER;
182         }
183         _SECURE_LOGI("Check trusted remote port (%s):(%s).", remote_app_id, remote_port);
184         return convert_to_tizen_error((messageport_error_e)messageport_check_trusted_remote_port(remote_app_id, remote_port, exist));
185 }
186
187 int message_port_send_message(const char *remote_app_id, const char *remote_port, bundle *message)
188 {
189         int ret;
190         if (remote_app_id == NULL || remote_port == NULL || message == NULL) {
191                 _LOGE("[MESSAGE_PORT_ERROR_INVALID_PARAMETER] NULL value is not allowed.");
192                 return MESSAGE_PORT_ERROR_INVALID_PARAMETER;
193         }
194
195         _SECURE_LOGI("Send a message to (%s):(%s).", remote_app_id, remote_port);
196         pthread_mutex_lock(&__mutex);
197         ret = messageport_send_message(remote_app_id, remote_port, message);
198         pthread_mutex_unlock(&__mutex);
199
200         return convert_to_tizen_error((messageport_error_e)ret);
201 }
202
203 int message_port_send_trusted_message(const char *remote_app_id, const char *remote_port, bundle *message)
204 {
205         int ret;
206         if (remote_app_id == NULL || remote_port == NULL || message == NULL) {
207                 _LOGE("[MESSAGE_PORT_ERROR_INVALID_PARAMETER] NULL value is not allowed.");
208                 return MESSAGE_PORT_ERROR_INVALID_PARAMETER;
209         }
210         _SECURE_LOGI("Send a trusted message to (%s):(%s).", remote_app_id, remote_port);
211
212         pthread_mutex_lock(&__mutex);
213         ret = messageport_send_trusted_message(remote_app_id, remote_port, message);
214         pthread_mutex_unlock(&__mutex);
215
216         return convert_to_tizen_error((messageport_error_e)ret);
217 }
218
219 int message_port_send_message_with_local_port(const char *remote_app_id, const char *remote_port, bundle *message, int local_port_id)
220 {
221         int ret;
222         if (remote_app_id == NULL || remote_port == NULL || message == NULL) {
223                 _LOGE("[MESSAGE_PORT_ERROR_INVALID_PARAMETER] NULL value is not allowed.");
224                 return MESSAGE_PORT_ERROR_INVALID_PARAMETER;
225         } else if (local_port_id <= 0) {
226                 _LOGE("[MESSAGEPORT_ERROR_INVALID_PARAMETER] Neither 0 nor negative value is allowed.");
227                 return MESSAGE_PORT_ERROR_INVALID_PARAMETER;
228         } else {
229
230                 message_port_callback_item *item = NULL;
231                 message_port_callback_item *trusted_item = NULL;
232
233                 if (__listeners != NULL)
234                         item = (message_port_callback_item *)g_hash_table_lookup(__listeners, GINT_TO_POINTER(local_port_id));
235
236                 if (item == NULL && __trusted_listeners != NULL)
237                         trusted_item = (message_port_callback_item *)g_hash_table_lookup(__trusted_listeners, GINT_TO_POINTER(local_port_id));
238
239
240                 if (item == NULL && trusted_item == NULL) {
241                         _LOGE("[MESSAGE_PORT_ERROR_PORT_NOT_FOUND] The local port ID (%d) is not registered.", local_port_id);
242                         return MESSAGE_PORT_ERROR_PORT_NOT_FOUND;
243                 }
244         }
245
246         _SECURE_LOGI("Send a message to (%s):(%s) and listen at the local port ID (%d).", remote_app_id, remote_port, local_port_id);
247         pthread_mutex_lock(&__mutex);
248         ret = messageport_send_bidirectional_message(local_port_id, remote_app_id, remote_port, message);
249         pthread_mutex_unlock(&__mutex);
250
251         return convert_to_tizen_error((messageport_error_e)ret);
252 }
253
254 int message_port_send_trusted_message_with_local_port(const char *remote_app_id, const char *remote_port, bundle *message, int local_port_id)
255 {
256         int ret;
257         if (remote_app_id == NULL || remote_port == NULL || message == NULL) {
258                 _LOGE("[MESSAGE_PORT_ERROR_INVALID_PARAMETER] NULL value is not allowed.");
259                 return MESSAGE_PORT_ERROR_INVALID_PARAMETER;
260         } else if (local_port_id <= 0) {
261                 _LOGE("[MESSAGEPORT_ERROR_INVALID_PARAMETER] Neither 0 nor negative value is allowed.");
262                 return MESSAGE_PORT_ERROR_INVALID_PARAMETER;
263         } else {
264                 message_port_callback_item *item = NULL;
265                 message_port_callback_item *trusted_item = NULL;
266
267                 if (__listeners != NULL)
268                         item = (message_port_callback_item *)g_hash_table_lookup(__listeners, GINT_TO_POINTER(local_port_id));
269
270                 if (item == NULL && __trusted_listeners != NULL)
271                         trusted_item = (message_port_callback_item *)g_hash_table_lookup(__trusted_listeners, GINT_TO_POINTER(local_port_id));
272
273                 if (item == NULL && trusted_item == NULL) {
274                         _LOGE("[MESSAGE_PORT_ERROR_PORT_NOT_FOUND] The local port ID (%d) is not registered.", local_port_id);
275                         return MESSAGE_PORT_ERROR_PORT_NOT_FOUND;
276                 }
277         }
278
279         _SECURE_LOGI("Send a trusted message to (%s):(%s) and listen at the local port ID (%d).", remote_app_id, remote_port, local_port_id);
280         pthread_mutex_lock(&__mutex);
281         ret = messageport_send_bidirectional_trusted_message(local_port_id, remote_app_id, remote_port, message);
282         pthread_mutex_unlock(&__mutex);
283
284         return convert_to_tizen_error((messageport_error_e)ret);
285 }
286