Fix for PLM issue :Increased worker size
[platform/core/pim/pims-ipc.git] / src / pims-ipc-svc.c
1 /*
2  * PIMS IPC
3  *
4  * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the License);
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an AS IS BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #include <unistd.h>
20 #include <stdlib.h>
21 #include <stdint.h>
22 #include <unistd.h>
23 #include <error.h>
24 #include <glib.h>
25
26 #include "pims-internal.h"
27 #include "pims-socket.h"
28 #include "pims-ipc-data.h"
29 #include "pims-ipc-data-internal.h"
30 #include "pims-ipc-utils.h"
31 #include "pims-ipc-pubsub.h"
32 #include "pims-ipc-worker.h"
33 #include "pims-ipc-svc.h"
34
35 #define PIMS_IPC_WORKERS_DEFAULT_MAX_COUNT  3
36
37 static pims_ipc_svc_s *_g_singleton = NULL;
38
39 gboolean svc_map_client_worker(gpointer user_data)
40 {
41         char *client_id = user_data;
42         pims_ipc_worker_data_s *worker_data;
43
44         worker_data = worker_get_idle_worker(_g_singleton, client_id);
45         if (NULL == worker_data) {
46                 ERR("worker_get_idle_worker() Fail");
47                 return G_SOURCE_CONTINUE;
48         }
49         return G_SOURCE_REMOVE;
50 }
51
52 API int pims_ipc_svc_init(char *service, gid_t group, mode_t mode)
53 {
54         RETVM_IF(_g_singleton, -1, "Already exist");
55
56         int ret = 0;
57
58         _g_singleton = g_new0(pims_ipc_svc_s, 1);
59         if (NULL == _g_singleton) {
60                 ERR("g_new0() Fail");
61                 return -1;
62         }
63
64         ret = cynara_initialize(&_g_singleton->cynara, NULL);
65         if (CYNARA_API_SUCCESS != ret) {
66                 char errmsg[1024] = {0};
67                 cynara_strerror(ret, errmsg, sizeof(errmsg));
68                 ERR("cynara_initialize() Fail(%d,%s)", ret, errmsg);
69                 return -1;
70         }
71
72         _g_singleton->service = g_strdup(service);
73         _g_singleton->group = group;
74         _g_singleton->mode = mode;
75         _g_singleton->workers_max_count = PIMS_IPC_WORKERS_DEFAULT_MAX_COUNT;
76
77         /* client id - worker_fd mapping */
78         _g_singleton->client_worker_map = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
79         ASSERT(_g_singleton->client_worker_map);
80
81         pthread_mutex_init(&_g_singleton->manager_list_hangup_mutex, 0);
82         _g_singleton->manager_list_hangup = NULL;
83
84         worker_init();
85         client_init();
86
87         pthread_mutex_init(&_g_singleton->cynara_mutex, 0);
88         return 0;
89 }
90
91 static void __remove_client_fd_map(pims_ipc_svc_s *ipc_svc)
92 {
93         GList *next, *cursor;
94         pims_ipc_client_map_s *client;
95
96         cursor = g_list_first(ipc_svc->client_id_fd_map);
97         while (cursor) {
98                 next = cursor->next;
99                 client = cursor->data;
100                 worker_stop_client_worker(ipc_svc, client->id);
101                 free(client->id);
102                 free(client);
103                 cursor = next;
104         }
105         g_list_free(ipc_svc->client_id_fd_map);
106 }
107
108 API int pims_ipc_svc_deinit(void)
109 {
110         RETV_IF(NULL == _g_singleton, -1);
111
112         g_free(_g_singleton->service);
113
114         pthread_mutex_destroy(&_g_singleton->manager_list_hangup_mutex);
115         g_list_free_full(_g_singleton->manager_list_hangup, g_free);
116
117         __remove_client_fd_map(_g_singleton);
118         worker_deinit();
119         g_hash_table_destroy(_g_singleton->client_worker_map);
120         client_deinit();
121
122         pthread_mutex_lock(&_g_singleton->cynara_mutex);
123         int ret = cynara_finish(_g_singleton->cynara);
124         if (CYNARA_API_SUCCESS != ret) {
125                 char errmsg[1024] = {0};
126                 cynara_strerror(ret, errmsg, sizeof(errmsg));
127                 ERR("cynara_finish() Fail(%d,%s)", ret, errmsg);
128         }
129         pthread_mutex_unlock(&_g_singleton->cynara_mutex);
130         pthread_mutex_destroy(&_g_singleton->cynara_mutex);
131
132         g_free(_g_singleton);
133         _g_singleton = NULL;
134
135         return 0;
136 }
137
138 API int pims_ipc_svc_register(char *module, char *function,
139                 pims_ipc_svc_call_cb callback, void *userdata)
140 {
141         gchar *call_id = NULL;
142         pims_ipc_svc_cb_s *cb_data = NULL;
143
144         RETV_IF(NULL == module, -1);
145         RETV_IF(NULL == function, -1);
146         RETV_IF(NULL == callback, -1);
147
148         cb_data = calloc(1, sizeof(pims_ipc_svc_cb_s));
149         if (NULL == cb_data) {
150                 ERR("calloc() Fail");
151                 return -1;
152         }
153
154         call_id = PIMS_IPC_MAKE_CALL_ID(module, function);
155         VERBOSE("register cb id[%s]", call_id);
156
157         cb_data->callback = callback;
158         cb_data->user_data = userdata;
159
160         worker_set_callback(call_id, cb_data);
161
162         return 0;
163 }
164
165 API void pims_ipc_svc_run_main_loop(GMainLoop **main_loop)
166 {
167         if (*main_loop == NULL)
168                 *main_loop = g_main_loop_new(NULL, FALSE);
169
170         pubsub_start();
171
172         if (_g_singleton) {
173                 /* launch worker threads in advance */
174                 worker_start_idle_worker(_g_singleton);
175                 socket_set_handler(_g_singleton);
176         }
177
178         g_main_loop_run(*main_loop);
179
180         worker_stop_idle_worker();
181         pubsub_stop();
182         g_main_loop_unref(*main_loop);
183         *main_loop = NULL;
184 }
185
186 API bool pims_ipc_svc_check_privilege(pims_ipc_h ipc, char *privilege)
187 {
188         int ret;
189         int pid = (int)ipc;
190
191         RETV_IF(NULL == privilege, false);
192
193         pims_ipc_client_info_s *client_info = NULL;
194         client_info = client_get_info(pid);
195         if (NULL == client_info) {
196                 ERR("client_info is NULL");
197                 return false;
198         }
199
200         pthread_mutex_lock(&_g_singleton->cynara_mutex);
201         ret = cynara_check(_g_singleton->cynara, client_info->smack,
202                         client_info->client_session, client_info->uid, privilege);
203         pthread_mutex_unlock(&_g_singleton->cynara_mutex);
204
205         client_destroy_info(client_info);
206
207         if (CYNARA_API_ACCESS_ALLOWED == ret)
208                 return true;
209
210         return false;
211 }
212
213 API int pims_ipc_svc_get_smack_label(pims_ipc_h ipc, char **p_smack)
214 {
215         pims_ipc_client_info_s *client_info = NULL;
216         int pid = (int)ipc;
217
218         client_info = client_get_info(pid);
219         if (NULL == client_info) {
220                 ERR("client_info is NULL");
221                 return false;
222         }
223
224         if (client_info->smack) {
225                 *p_smack = strdup(client_info->smack);
226                 if (NULL == *p_smack) {
227                         ERR("strdup() return NULL");
228                         client_destroy_info(client_info);
229                         return -1;
230                 }
231         }
232
233         client_destroy_info(client_info);
234         return 0;
235 }
236