3 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <sys/types.h>
21 #include <sys/socket.h>
27 #include <glib/gprintf.h>
29 #include "utility/sync_util.h"
30 #include "data-adapter/agent_handler_manager.h"
31 #include "fsapi/operation.h"
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"
39 #define EVENT_RETRY_COUNT 2000
42 #define EXPORT_API __attribute__ ((visibility("default")))
45 #ifndef SYNC_AGENT_LOG
47 #define LOG_TAG "AF_EVENT"
50 static int _event_server_socket_id = 0;
52 static pthread_t event_handler_thread_id;
54 static void *_event_listener(void *arg);
56 static void __dispatch_event(int event_num, sync_agent_event_data_s * request, sync_agent_event_data_s * response);
58 EXPORT_API sync_agent_event_error_e sync_agent_run_event_handler(unsigned long int *thread_id)
62 _DEBUG_INFO("sync_agent_run_event_handler() start\n");
64 pthread_create(&event_handler_thread_id, 0, _event_listener, 0);
66 *thread_id = event_handler_thread_id;
70 return SYNC_AGENT_EVENT_SUCCESS;
73 EXPORT_API sync_agent_event_error_e sync_agent_clean_event_handler()
77 sync_agent_event_error_e event_err = event_clean_event_spec();
78 if (event_err != SYNC_AGENT_EVENT_SUCCESS) {
79 _DEBUG_ERROR("Fail event_clean_event_spec : %d", event_err);
81 _DEBUG_INFO("Success event_clean_event_spec : %d", event_err);
83 event_err = event_clean_noti_spec();
84 if (event_err != SYNC_AGENT_EVENT_SUCCESS) {
85 _DEBUG_ERROR("Fail event_clean_noti_spec : %d", event_err);
87 _DEBUG_INFO("Success event_clean_noti_spec : %d", event_err);
90 if (_event_server_socket_id != 0) {
91 close(_event_server_socket_id);
92 _event_server_socket_id = 0;
95 pthread_cancel(event_handler_thread_id);
99 return SYNC_AGENT_EVENT_SUCCESS;
102 EXPORT_API sync_agent_event_error_e sync_agent_set_event_callback(int event_num, sync_agent_event_cb callback)
108 return event_register_event_callback(event_num, callback);
111 EXPORT_API sync_agent_event_data_s *sync_agent_create_noti(int noti_num)
115 sync_agent_event_data_s *noti = (sync_agent_event_data_s *) calloc(1, sizeof(sync_agent_event_data_s));
117 _DEBUG_ERROR("Memory malloc FAILED. [noti]");
120 noti->event_num = noti_num;
123 char *serialized_data = (char *)calloc(EVENT_MAX_STREAM_SIZE, sizeof(char));
124 if (serialized_data == NULL) {
125 _DEBUG_ERROR("CALLOC failed !!!");
126 sync_agent_free_event_data(noti);
129 noti->size = serialized_data;
130 noti->data = serialized_data + 1;
132 sync_agent_append_event_data_param(noti, SYNC_AGENT_EVENT_PARAM_TYPE_INTEGER, ¬i_num);
139 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)
143 if (noti_key == NULL) {
144 _DEBUG_ERROR("noti key is NULL !!");
145 *error = SYNC_AGENT_EVENT_IPC_ERR;
150 _DEBUG_ERROR("sync_agent_event_data_s is NULL !!");
151 *error = SYNC_AGENT_EVENT_IPC_ERR;
155 *error = SYNC_AGENT_EVENT_SUCCESS;
156 const char *communication_path = NULL;
158 noti_type_e noti_type = event_get_noti_type(noti_key, noti->event_num);
161 case NOTI_TYPE_SIMPLE:
162 communication_path = event_get_noti_path(noti_key);
165 *error = SYNC_AGENT_EVENT_IPC_ERR;
170 _DEBUG_INFO("noti num : %d", noti->event_num);
171 _DEBUG_INFO("noti_type : %d", noti_type);
172 _DEBUG_INFO("communication_path : %s", communication_path);
174 sync_agent_event_data_s *reply_msg = NULL;
175 int send_data_size = (noti->data - noti->size) + 1;
177 if (sync_agent_is_existing_fs(communication_path)) {
179 fp = fopen(communication_path, "w");
181 if (fwrite((void *)(noti->size), sizeof(char), send_data_size, fp) <= 0) {
182 _DEBUG_ERROR("fwrite() failed !!");
183 *error = SYNC_AGENT_EVENT_IPC_ERR;
187 _DEBUG_INFO("fwrite() success !!");
191 _DEBUG_ERROR("fopen( %s ) failed !!", communication_path);
192 *error = SYNC_AGENT_EVENT_IPC_ERR;
196 _DEBUG_ERROR("file ( %s ) does not exist !!", communication_path);
197 *error = SYNC_AGENT_EVENT_IPC_ERR;
206 EXPORT_API void sync_agent_free_noti(sync_agent_event_data_s * noti)
211 sync_agent_free_event_data(noti);
217 static void *_event_listener(void *arg)
221 signal(SIGPIPE, SIG_IGN);
225 socklen_t client_len;
226 struct sockaddr_un clientaddr, serveraddr;
230 const char *communication_path = event_get_event_path();
231 _DEBUG_TRACE("event_path : %s", communication_path);
233 if (sync_agent_is_existing_fs(communication_path)) {
234 _DEBUG_TRACE("%s file is exist !!");
235 if (unlink(communication_path) == -1) { /* when file exist, remove previous file */
236 _DEBUG_ERROR("unlink failed ( %s ), ERROR NUM [%d] !!", communication_path, errno);
239 _DEBUG_TRACE("unlink success !!");
242 _DEBUG_TRACE("%s file is not exist !!");
245 client_len = sizeof(clientaddr);
246 if ((_event_server_socket_id = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
250 bzero(&serveraddr, sizeof(serveraddr));
251 serveraddr.sun_family = AF_UNIX;
252 if (communication_path != NULL) {
253 buf_len = g_strlcpy(serveraddr.sun_path, communication_path, sizeof(serveraddr.sun_path));
254 if (buf_len >= sizeof(serveraddr.sun_path)) {
255 _DEBUG_ERROR("serveraddr.sun_path buffer overflow !!");
259 _DEBUG_ERROR("communication_path is NULL !!");
263 state = bind(_event_server_socket_id, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
265 _DEBUG_ERROR("bind failed !!");
269 mode_t sock_mode = (S_IRWXU | S_IRWXG | S_IRWXO);
270 if (chmod(communication_path, sock_mode) == -1) {
271 _DEBUG_ERROR("chmod failed !! ( err : %d )", errno);
275 state = listen(_event_server_socket_id, 5);
277 _DEBUG_ERROR("listen failed !!");
282 _DEBUG_TRACE("In EventHandler loop=\n");
284 char inbuf[EVENT_MAX_STREAM_SIZE + 1];
285 char outbuf[EVENT_MAX_STREAM_SIZE + 1];
286 memset(inbuf, 0x00, EVENT_MAX_STREAM_SIZE + 1);
287 memset(outbuf, 0x00, EVENT_MAX_STREAM_SIZE + 1);
288 sync_agent_event_data_s request;
289 sync_agent_event_data_s response;
290 request.data = inbuf;
291 response.data = outbuf;
292 event_init_event_data_iter(&request);
293 event_init_event_data_iter(&response);
295 client_sockfd = accept(_event_server_socket_id, (struct sockaddr *)&clientaddr, &client_len);
296 if (client_sockfd < 0) {
297 _DEBUG_ERROR("socket accept() failed !!");
300 _DEBUG_TRACE("accept() was called\n");
302 result = read(client_sockfd, (void *)inbuf, EVENT_MAX_STREAM_SIZE);
303 if (result <= 0 || result > EVENT_MAX_STREAM_SIZE) {
304 _DEBUG_ERROR("read failed !!");
305 close(client_sockfd);
308 if (strlen(inbuf) <= 0 || strlen(inbuf) > EVENT_MAX_STREAM_SIZE) {
309 _DEBUG_ERROR("socket data read : size OUT OF BOUND !!");
310 close(client_sockfd);
315 sync_agent_get_event_data_param_int(&request, &event_num);
316 _DEBUG_TRACE("Received Event Number : %d\n", event_num);
318 __dispatch_event(event_num, &request, &response);
320 * need synchronous response case
322 event_type_e event_type = event_get_event_type(event_num);
323 if (event_type == EVENT_TYPE_NEED_RESPONSE) {
324 if (event_get_event_data_element_size(&response) > 0) {
325 int byte_size = event_get_event_data_byte_size(&response);
326 int write_ret = write(client_sockfd, outbuf, byte_size);
327 if (write_ret != byte_size) {
328 _DEBUG_ERROR("write() failed !!");
333 close(client_sockfd);
341 static void __dispatch_event(int event_num, sync_agent_event_data_s * request, sync_agent_event_data_s * response)
345 retm_if(request == NULL, "sync_agent_event_data_s is NULL !!");
346 retm_if(response == NULL, "sync_agent_event_data_s is NULL !!");
348 sync_agent_event_cb event_callback = event_get_event_callback(event_num);
349 retm_if(event_callback == NULL, "event_get_event_callback return value is NULL !!");
351 event_callback(request, response);