[Internal: merge private->RSA , Patch create momanager.db]
[platform/core/system/sync-agent.git] / src / framework / event / handler.c
1 /*
2  * sync-agent
3  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
4  *
5  * Licensed under the Apache License, Version 2.0 (the License);
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include <pthread.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <sys/socket.h>
22 #include <sys/un.h>
23 #include <unistd.h>
24 #include <fcntl.h>
25 #include <errno.h>
26 #include <glib.h>
27 #include <glib/gprintf.h>
28
29 #include "utility/sync_util.h"
30 #include "data-adapter/agent_handler_manager.h"
31 #include "fsapi/operation.h"
32
33 #include "event/util.h"
34 #include "event/data_accessor.h"
35 #include "event/data_accessor_internal.h"
36 #include "event/config.h"
37 #include "event/handler.h"
38
39 #define EVENT_RETRY_COUNT               2000
40
41 #ifndef EXPORT_API
42 #define EXPORT_API __attribute__ ((visibility("default")))
43 #endif
44
45 #ifndef SYNC_AGENT_LOG
46 #undef LOG_TAG
47 #define LOG_TAG "AF_EVENT"
48 #endif
49
50 static int _event_server_socket_id = 0;
51
52 static pthread_t event_handler_thread_id;
53
54 static void *_event_listener(void *arg);
55
56 static void __dispatch_event(int event_num, sync_agent_event_data_s * request, sync_agent_event_data_s * response);
57
58 EXPORT_API sync_agent_event_error_e sync_agent_run_event_handler(unsigned long int *thread_id)
59 {
60         _EXTERN_FUNC_ENTER;
61
62         _DEBUG_INFO("sync_agent_run_event_handler() start\n");
63
64         int status_thread_create = 0;
65         status_thread_create = pthread_create(&event_handler_thread_id, 0, _event_listener, 0);
66         if(status_thread_create != 0) {
67                 _DEBUG_WARNING("pthread_create [%d]", status_thread_create );
68                 _EXTERN_FUNC_EXIT;
69                 return SYNC_AGENT_EVENT_FAIL;
70         }
71
72         *thread_id = event_handler_thread_id;
73
74         _EXTERN_FUNC_EXIT;
75
76         return SYNC_AGENT_EVENT_SUCCESS;
77 }
78
79 EXPORT_API sync_agent_event_error_e sync_agent_clean_event_handler()
80 {
81         _EXTERN_FUNC_ENTER;
82
83         sync_agent_event_error_e event_err = event_clean_event_spec();
84         if (event_err != SYNC_AGENT_EVENT_SUCCESS) {
85                 _DEBUG_ERROR("Fail event_clean_event_spec : %d", event_err);
86         } else {
87                 _DEBUG_INFO("Success event_clean_event_spec : %d", event_err);
88         }
89         event_err = event_clean_noti_spec();
90         if (event_err != SYNC_AGENT_EVENT_SUCCESS) {
91                 _DEBUG_ERROR("Fail event_clean_noti_spec : %d", event_err);
92         } else {
93                 _DEBUG_INFO("Success event_clean_noti_spec : %d", event_err);
94         }
95
96         if (_event_server_socket_id != 0) {
97                 close(_event_server_socket_id);
98                 _event_server_socket_id = 0;
99         }
100
101         pthread_cancel(event_handler_thread_id);
102
103         _EXTERN_FUNC_EXIT;
104
105         return SYNC_AGENT_EVENT_SUCCESS;
106 }
107
108 EXPORT_API sync_agent_event_error_e sync_agent_set_event_callback(int event_num, sync_agent_event_cb callback)
109 {
110         _EXTERN_FUNC_ENTER;
111
112         _EXTERN_FUNC_EXIT;
113
114         return event_register_event_callback(event_num, callback);
115 }
116
117 EXPORT_API sync_agent_event_data_s *sync_agent_create_noti(int noti_num)
118 {
119         _EXTERN_FUNC_ENTER;
120
121         sync_agent_event_data_s *noti = (sync_agent_event_data_s *) calloc(1, sizeof(sync_agent_event_data_s));
122         if (noti == NULL) {
123                 _DEBUG_ERROR("Memory malloc FAILED. [noti]");
124                 return noti;
125         } else {
126                 noti->event_num = noti_num;
127         }
128
129         char *serialized_data = (char *)calloc(EVENT_MAX_STREAM_SIZE, sizeof(char));
130         if (serialized_data == NULL) {
131                 _DEBUG_ERROR("CALLOC failed !!!");
132                 sync_agent_free_event_data(noti);
133                 return NULL;
134         }
135         noti->size = serialized_data;
136         noti->data = serialized_data + 1;
137
138         sync_agent_append_event_data_param(noti, SYNC_AGENT_EVENT_PARAM_TYPE_INTEGER, &noti_num);
139
140         _EXTERN_FUNC_EXIT;
141
142         return noti;
143 }
144
145 EXPORT_API sync_agent_event_data_s *sync_agent_send_noti(const char *noti_key, sync_agent_event_data_s * noti, sync_agent_confirm_ipc_cancel_cb confirm_cancel, void *user_data, sync_agent_event_error_e * error)
146 {
147         _EXTERN_FUNC_ENTER;
148
149         if (noti_key == NULL) {
150                 _DEBUG_ERROR("noti key is NULL !!");
151                 *error = SYNC_AGENT_EVENT_IPC_ERR;
152                 return NULL;
153         }
154
155         if (noti == NULL) {
156                 _DEBUG_ERROR("sync_agent_event_data_s is NULL !!");
157                 *error = SYNC_AGENT_EVENT_IPC_ERR;
158                 return NULL;
159         }
160
161         *error = SYNC_AGENT_EVENT_SUCCESS;
162         const char *communication_path = NULL;
163
164         noti_type_e noti_type = event_get_noti_type(noti_key, noti->event_num);
165
166         switch (noti_type) {
167         case NOTI_TYPE_SIMPLE:
168                 communication_path = event_get_noti_path(noti_key);
169                 break;
170         default:
171                 *error = SYNC_AGENT_EVENT_IPC_ERR;
172                 return NULL;
173                 break;
174         }
175
176         _DEBUG_INFO("noti num : %d", noti->event_num);
177         _DEBUG_INFO("noti_type : %d", noti_type);
178         _DEBUG_INFO("communication_path : %s", communication_path);
179
180         sync_agent_event_data_s *reply_msg = NULL;
181         int send_data_size = (noti->data - noti->size) + 1;
182
183         if (sync_agent_is_existing_fs(communication_path)) {
184                 FILE *fp = NULL;
185                 fp = fopen(communication_path, "w");
186                 if (fp != NULL) {
187                         if (fwrite((void *)(noti->size), sizeof(char), send_data_size, fp) <= 0) {
188                                 _DEBUG_ERROR("fwrite() failed !!");
189                                 *error = SYNC_AGENT_EVENT_IPC_ERR;
190                                 fclose(fp);
191                                 return NULL;
192                         } else {
193                                 _DEBUG_INFO("fwrite() success !!");
194                                 fclose(fp);
195                         }
196                 } else {
197                         _DEBUG_ERROR("fopen( %s ) failed  !!", communication_path);
198                         *error = SYNC_AGENT_EVENT_IPC_ERR;
199                         return NULL;
200                 }
201         } else {
202                 _DEBUG_ERROR("file ( %s ) does not exist !!", communication_path);
203                 *error = SYNC_AGENT_EVENT_IPC_ERR;
204                 return NULL;
205         }
206
207         _EXTERN_FUNC_EXIT;
208
209         return reply_msg;
210 }
211
212 EXPORT_API void sync_agent_free_noti(sync_agent_event_data_s * noti)
213 {
214         _EXTERN_FUNC_ENTER;
215
216         if (noti != NULL) {
217                 sync_agent_free_event_data(noti);
218         }
219
220         _EXTERN_FUNC_EXIT;
221 }
222
223 static void *_event_listener(void *arg)
224 {
225         _INNER_FUNC_ENTER;
226
227         signal(SIGPIPE, SIG_IGN);
228
229         int client_sockfd = -1;
230         int state;
231         socklen_t client_len;
232         struct sockaddr_un clientaddr, serveraddr;
233         int buf_len = 0;
234         int result = 0;
235
236         const char *communication_path = event_get_event_path();
237         _DEBUG_TRACE("event_path : %s", communication_path);
238
239         if (sync_agent_is_existing_fs(communication_path)) {
240                 _DEBUG_TRACE("%s file is exist !!");
241                 if (unlink(communication_path) == -1) { /* when file exist, remove previous file */
242                         _DEBUG_ERROR("unlink failed ( %s ), ERROR NUM [%d] !!", communication_path, errno);
243                         return NULL;
244                 } else {
245                         _DEBUG_TRACE("unlink success !!");
246                 }
247         } else {
248                 _DEBUG_TRACE("%s file is not exist !!");
249         }
250
251         client_len = sizeof(clientaddr);
252         _DEBUG_INFO("_event_listener - client_len: [%d]",client_len);
253         if ((_event_server_socket_id = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
254                 return NULL;
255         }
256
257         bzero(&serveraddr, sizeof(serveraddr));
258         serveraddr.sun_family = AF_UNIX;
259         if (communication_path != NULL) {
260                 buf_len = g_strlcpy(serveraddr.sun_path, communication_path, sizeof(serveraddr.sun_path));
261                 if (buf_len >= sizeof(serveraddr.sun_path)) {
262                         _DEBUG_ERROR("serveraddr.sun_path buffer overflow !!");
263                         return NULL;
264                 }
265         } else {
266                 _DEBUG_ERROR("communication_path is NULL !!");
267                 return NULL;
268         }
269
270         state = bind(_event_server_socket_id, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
271         if (state == -1) {
272                 _DEBUG_ERROR("bind failed !!");
273                 return NULL;
274         }
275
276         mode_t sock_mode = (S_IRWXU | S_IRWXG | S_IRWXO);
277         if (chmod(communication_path, sock_mode) == -1) {
278                 _DEBUG_ERROR("chmod failed !! ( err : %d )", errno);
279 //              return NULL;
280         }
281
282         state = listen(_event_server_socket_id, 5);
283         if (state == -1) {
284                 _DEBUG_ERROR("listen failed !!");
285                 return NULL;
286         }
287
288         while (1) {
289                 _DEBUG_TRACE("In EventHandler loop=\n");
290
291                 char * inbuf = NULL;
292                 char * outbuf = NULL;
293                 inbuf = (char*)malloc(sizeof(char)*(EVENT_MAX_STREAM_SIZE + 1));
294                 if(inbuf == NULL) {
295                         _DEBUG_ERROR("inbuf malloc failed!!");
296                         goto error;
297                 }
298
299                 outbuf= (char*)malloc(sizeof(char)*(EVENT_MAX_STREAM_SIZE + 1));
300                 if(outbuf == NULL) {
301                         _DEBUG_ERROR("outbuf malloc failed!!");
302                         goto error;
303                 }
304
305                 memset(inbuf, 0x00, EVENT_MAX_STREAM_SIZE + 1);
306                 memset(outbuf, 0x00, EVENT_MAX_STREAM_SIZE + 1);
307                 sync_agent_event_data_s request = {0,NULL,NULL};
308                 sync_agent_event_data_s response = {0,NULL,NULL};
309
310                 request.data = inbuf;
311                 response.data = outbuf;
312                 event_init_event_data_iter(&request);
313                 event_init_event_data_iter(&response);
314
315                 client_sockfd = accept(_event_server_socket_id, (struct sockaddr *)&clientaddr, &client_len);
316
317                 if (client_sockfd < 0) {
318                         _DEBUG_ERROR("socket accept() failed !!");
319                         goto error;
320                 }
321                 _DEBUG_TRACE("accept() was called\n");
322                 _DEBUG_INFO("_event_listener - client_sockfd: [%d]",client_sockfd);
323
324                 result = read(client_sockfd, (void *)inbuf, EVENT_MAX_STREAM_SIZE);
325                 if (result <= 0 || result > EVENT_MAX_STREAM_SIZE) {
326                         _DEBUG_ERROR("read failed !!");
327                         goto error;
328                 }
329 /*
330                 _DEBUG_INFO("read result [%d]", result);
331
332                 int print_i = 0;
333                 for( print_i = 0; print_i < result ; print_i++)
334                 {
335                         _DEBUG_INFO(" 0x%x ", inbuf[print_i]);
336                 }
337                 _DEBUG_INFO("request.event_num [%d]", request.event_num);
338                 _DEBUG_INFO("request.size [ox%x]", *(request.size));
339                 _DEBUG_INFO("request.data [0x%x]", *(request.data));
340 */
341
342                 int event_num = 0;
343                 sync_agent_get_event_data_param_int(&request, &event_num);
344                 _DEBUG_TRACE("Received Event Number : %d\n", event_num);
345
346                 __dispatch_event(event_num, &request, &response);
347
348                 // need synchronous response case
349                 event_type_e event_type = event_get_event_type(event_num);
350                 if (event_type == EVENT_TYPE_NEED_RESPONSE) {
351                         if (event_get_event_data_element_size(&response) > 0) {
352                                 int byte_size = event_get_event_data_byte_size(&response);
353                                 int write_ret = write(client_sockfd, outbuf, byte_size);
354                                 if (write_ret != byte_size) {
355                                         _DEBUG_ERROR("write() failed !!");
356                                 }
357                         }
358                 }
359
360  error:
361
362                 if (inbuf) {
363                         free(inbuf);
364                         inbuf = NULL;
365                 }
366
367                 if (outbuf) {
368                         free(outbuf);
369                         outbuf = NULL;
370                 }
371
372                 if (client_sockfd >= 0 ) {
373                         close(client_sockfd);
374                         client_sockfd = -1;
375                 }
376         }
377
378         _INNER_FUNC_EXIT;
379
380         return NULL;
381 }
382
383 static void __dispatch_event(int event_num, sync_agent_event_data_s * request, sync_agent_event_data_s * response)
384 {
385         _INNER_FUNC_ENTER;
386
387         retm_if(request == NULL, "sync_agent_event_data_s is NULL !!");
388         retm_if(response == NULL, "sync_agent_event_data_s is NULL !!");
389
390         sync_agent_event_cb event_callback = event_get_event_callback(event_num);
391         retm_if(event_callback == NULL, "event_get_event_callback return value is NULL !!");
392
393         event_callback(request, response);
394         _INNER_FUNC_EXIT;
395 }