Add NULL check logic for message callback
[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         if (remote_app_id == NULL || remote_port == NULL || message == NULL) {
190                 _LOGE("[MESSAGE_PORT_ERROR_INVALID_PARAMETER] NULL value is not allowed.");
191                 return MESSAGE_PORT_ERROR_INVALID_PARAMETER;
192         }
193         return convert_to_tizen_error((messageport_error_e)messageport_send_message(remote_app_id, remote_port, message));
194 }
195
196 int message_port_send_trusted_message(const char *remote_app_id, const char *remote_port, bundle *message)
197 {
198         if (remote_app_id == NULL || remote_port == NULL || message == NULL) {
199                 _LOGE("[MESSAGE_PORT_ERROR_INVALID_PARAMETER] NULL value is not allowed.");
200                 return MESSAGE_PORT_ERROR_INVALID_PARAMETER;
201         }
202         return convert_to_tizen_error((messageport_error_e)messageport_send_trusted_message(remote_app_id, remote_port, message));
203 }
204
205 int message_port_send_message_with_local_port(const char *remote_app_id, const char *remote_port, bundle *message, int local_port_id)
206 {
207         if (remote_app_id == NULL || remote_port == NULL || message == NULL) {
208                 _LOGE("[MESSAGE_PORT_ERROR_INVALID_PARAMETER] NULL value is not allowed.");
209                 return MESSAGE_PORT_ERROR_INVALID_PARAMETER;
210         } else if (local_port_id <= 0) {
211                 _LOGE("[MESSAGEPORT_ERROR_INVALID_PARAMETER] Neither 0 nor negative value is allowed.");
212                 return MESSAGE_PORT_ERROR_INVALID_PARAMETER;
213         } else {
214
215                 message_port_callback_item *item = NULL;
216                 message_port_callback_item *trusted_item = NULL;
217
218                 if (__listeners != NULL)
219                         item = (message_port_callback_item *)g_hash_table_lookup(__listeners, GINT_TO_POINTER(local_port_id));
220
221                 if (item == NULL && __trusted_listeners != NULL)
222                         trusted_item = (message_port_callback_item *)g_hash_table_lookup(__trusted_listeners, GINT_TO_POINTER(local_port_id));
223
224
225                 if (item == NULL && trusted_item == NULL) {
226                         _LOGE("[MESSAGE_PORT_ERROR_PORT_NOT_FOUND] The local port ID (%d) is not registered.", local_port_id);
227                         return MESSAGE_PORT_ERROR_PORT_NOT_FOUND;
228                 }
229         }
230
231         _SECURE_LOGI("Send a message to (%s):(%s) and listen at the local port ID (%d).", remote_app_id, remote_port, local_port_id);
232         return convert_to_tizen_error((messageport_error_e)messageport_send_bidirectional_message(local_port_id, remote_app_id, remote_port, message));
233 }
234
235 int message_port_send_trusted_message_with_local_port(const char *remote_app_id, const char *remote_port, bundle *message, int local_port_id)
236 {
237         if (remote_app_id == NULL || remote_port == NULL || message == NULL) {
238                 _LOGE("[MESSAGE_PORT_ERROR_INVALID_PARAMETER] NULL value is not allowed.");
239                 return MESSAGE_PORT_ERROR_INVALID_PARAMETER;
240         } else if (local_port_id <= 0) {
241                 _LOGE("[MESSAGEPORT_ERROR_INVALID_PARAMETER] Neither 0 nor negative value is allowed.");
242                 return MESSAGE_PORT_ERROR_INVALID_PARAMETER;
243         } else {
244                 message_port_callback_item *item = NULL;
245                 message_port_callback_item *trusted_item = NULL;
246
247                 if (__listeners != NULL)
248                         item = (message_port_callback_item *)g_hash_table_lookup(__listeners, GINT_TO_POINTER(local_port_id));
249
250                 if (item == NULL && __trusted_listeners != NULL)
251                         trusted_item = (message_port_callback_item *)g_hash_table_lookup(__trusted_listeners, GINT_TO_POINTER(local_port_id));
252
253                 if (item == NULL && trusted_item == NULL) {
254                         _LOGE("[MESSAGE_PORT_ERROR_PORT_NOT_FOUND] The local port ID (%d) is not registered.", local_port_id);
255                         return MESSAGE_PORT_ERROR_PORT_NOT_FOUND;
256                 }
257         }
258
259         _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);
260         return convert_to_tizen_error((messageport_error_e)messageport_send_bidirectional_trusted_message(local_port_id, remote_app_id, remote_port, message));
261 }
262