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>
26 #include <glib/gprintf.h>
29 #include <sys/inotify.h>
31 #include "utility/sync_util.h"
32 #include "fsapi/operation.h"
34 #include "event/config.h"
35 #include "event/util.h"
36 #include "event/data_accessor.h"
37 #include "event/data_accessor_internal.h"
38 #include "event/ui_api.h"
41 #define EXPORT_API __attribute__ ((visibility("default")))
44 #ifndef SYNC_AGENT_LOG
46 #define LOG_TAG "AF_EVENT_UI"
49 #define EVENT_SIZE (sizeof(struct inotify_event))
51 static int inotify_fd;
52 static int inotify_wd;
53 static int gsource_id;
55 static gboolean _agent_noti_listener(GIOChannel * p_src, GIOCondition cond, gpointer p_data);
57 static void __dispatch_noti(int noti_num, sync_agent_event_data_s * noti, sync_agent_event_error_e * error);
59 EXPORT_API sync_agent_event_data_s *sync_agent_create_event(int event_num)
63 sync_agent_event_data_s *event = (sync_agent_event_data_s *) malloc(sizeof(sync_agent_event_data_s));
65 _DEBUG_ERROR("Memory malloc FAILED. [event]");
68 event->event_num = event_num;
70 char *serialized_data = (char *)calloc(EVENT_MAX_STREAM_SIZE, sizeof(char));
71 if (serialized_data != NULL) {
72 event->size = serialized_data;
73 event->data = serialized_data + 1;
75 sync_agent_append_event_data_param(event, SYNC_AGENT_EVENT_PARAM_TYPE_INTEGER, &event_num);
86 EXPORT_API sync_agent_event_data_s *sync_agent_send_event(sync_agent_event_data_s * event, sync_agent_event_error_e * error)
91 _DEBUG_ERROR("sync_agent_event_data_s is NULL !!");
92 *error = SYNC_AGENT_EVENT_IPC_ERR;
96 *error = SYNC_AGENT_EVENT_SUCCESS;
99 struct sockaddr_un clientaddr;
102 client_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
103 if (client_sockfd == -1) {
104 _DEBUG_ERROR("socket create Error!!");
105 *error = SYNC_AGENT_EVENT_IPC_ERR;
109 bzero(&clientaddr, sizeof(clientaddr));
110 clientaddr.sun_family = AF_UNIX;
112 * select socket path, whether event type is response for notification
114 const char *communication_path = NULL;
115 event_type_e event_type = event_get_event_type(event->event_num);
116 switch (event_type) {
117 case EVENT_TYPE_NO_RESPONSE:
118 case EVENT_TYPE_NEED_RESPONSE:
119 communication_path = event_get_event_path();
125 if (communication_path == NULL) {
126 close(client_sockfd);
127 *error = SYNC_AGENT_EVENT_IPC_ERR;
131 _DEBUG_INFO("communication_path : %s", communication_path);
133 if (communication_path != NULL) {
134 buf_len = g_strlcpy(clientaddr.sun_path, communication_path, sizeof(clientaddr.sun_path));
135 if (buf_len >= sizeof(clientaddr.sun_path)) {
136 _DEBUG_ERROR("clientaddr.sun_path buffer overflow !!");
137 close(client_sockfd);
138 *error = SYNC_AGENT_EVENT_IPC_ERR;
142 _DEBUG_ERROR("communication_path is NULL !!");
143 close(client_sockfd);
144 *error = SYNC_AGENT_EVENT_IPC_ERR;
148 client_len = sizeof(clientaddr);
150 if (connect(client_sockfd, (struct sockaddr *)&clientaddr, client_len) < 0) {
151 _DEBUG_ERROR("socket connect error ( %d )", errno);
152 close(client_sockfd);
153 *error = SYNC_AGENT_EVENT_IPC_ERR;
157 int send_data_size = (event->data - event->size) + 1;
158 int write_ret = write(client_sockfd, (void *)(event->size), send_data_size);
159 if (write_ret == -1) {
160 _DEBUG_INFO("write() failed !!");
161 close(client_sockfd);
162 *error = SYNC_AGENT_EVENT_IPC_ERR;
166 if (event_type != EVENT_TYPE_NEED_RESPONSE) {
167 _DEBUG_INFO("Do not need synchronous response");
168 *error = SYNC_AGENT_EVENT_SUCCESS;
169 close(client_sockfd);
176 char *connection_result = (char *)calloc(EVENT_MAX_STREAM_SIZE, sizeof(char));
177 if (connection_result == NULL) {
178 _DEBUG_ERROR("Memory malloc FAILED. [connection_result]");
179 close(client_sockfd);
180 *error = SYNC_AGENT_EVENT_FAIL;
184 if (read(client_sockfd, connection_result, EVENT_MAX_STREAM_SIZE) <= 0) {
185 _DEBUG_ERROR("Socket Error - failed to read()");
186 if (connection_result != NULL)
187 free(connection_result);
188 close(client_sockfd);
189 *error = SYNC_AGENT_EVENT_IPC_ERR;
192 close(client_sockfd);
194 event_print_event_data(connection_result);
196 sync_agent_event_data_s *reply_msg = (sync_agent_event_data_s *) malloc(sizeof(sync_agent_event_data_s));
197 if (reply_msg == NULL) {
198 _DEBUG_ERROR("Memory malloc FAILED. [reply_msg]");
199 if (connection_result != NULL)
200 free(connection_result);
201 *error = SYNC_AGENT_EVENT_FAIL;
204 reply_msg->data = connection_result;
206 event_init_event_data_iter(reply_msg);
213 EXPORT_API sync_agent_event_error_e sync_agent_run_noti_listener(const char *noti_key)
217 retvm_if(noti_key == NULL, SYNC_AGENT_EVENT_FAIL, "noti key is NULL !!");
219 GIOChannel *gio_channel = NULL;
220 GSource *g_source = NULL;
223 _DEBUG_TRACE("noti_key : %s", noti_key);
225 const char *communication_path = event_get_noti_path(0);
226 _DEBUG_TRACE("Noti communication path : %s", communication_path);
228 if (sync_agent_is_existing_fs(communication_path)) {
229 _DEBUG_TRACE("%s file is exist !!");
230 if (unlink(communication_path) == -1) {
231 _DEBUG_ERROR("unlink failed ( %s ), ERROR NUM [%d] !!", communication_path, errno);
232 return SYNC_AGENT_EVENT_FAIL;
234 _DEBUG_TRACE("unlink success !!");
237 _DEBUG_TRACE("%s file is not exist !!");
240 int fd = creat(communication_path, S_IRWXU | S_IRWXG | S_IRWXO);
242 _DEBUG_ERROR("creat() failed !!");
243 return SYNC_AGENT_EVENT_FAIL;
245 _DEBUG_TRACE("%s file is created !!");
248 /* initialize an inotify instance */
249 inotify_fd = inotify_init();
250 if (inotify_fd == -1) {
251 _DEBUG_ERROR("inotify_init() failed !!");
252 return SYNC_AGENT_EVENT_FAIL;
255 /* change file's attribute */
256 result = fcntl(inotify_fd, F_SETFD, FD_CLOEXEC);
258 _DEBUG_ERROR("fcntl() failed !!");
259 return SYNC_AGENT_EVENT_FAIL;
261 result = fcntl(inotify_fd, F_SETFL, O_NONBLOCK);
263 _DEBUG_ERROR("fcntl() failed !!");
264 return SYNC_AGENT_EVENT_FAIL;
267 /* add a watch to an initialized inotify instance */
268 inotify_wd = inotify_add_watch(inotify_fd, communication_path, IN_CLOSE_WRITE);
269 if (inotify_wd == -1) {
270 _DEBUG_ERROR("inotify_add_watch() failed !!");
271 return SYNC_AGENT_EVENT_FAIL;
274 /* create a new GIOChannel given a file descriptor */
275 gio_channel = g_io_channel_unix_new(inotify_fd);
276 if (gio_channel == NULL) {
277 _DEBUG_ERROR("g_io_channel_unix_new() failed !!");
278 return SYNC_AGENT_EVENT_FAIL;
281 /* turn on nonblocking mode */
282 g_io_channel_set_flags(gio_channel, G_IO_FLAG_NONBLOCK, NULL);
284 /* create a GSource that's dispatched when condition is met for the given channel */
285 g_source = g_io_create_watch(gio_channel, G_IO_IN);
287 /* sets the priority of a source */
288 g_source_set_priority(g_source, G_PRIORITY_HIGH);
290 /* set the callback function for a source */
291 g_source_set_callback(g_source, (GSourceFunc) _agent_noti_listener, (gpointer) noti_key, NULL);
293 /* add a GSource to a context so that it will be executed within that context */
294 gsource_id = g_source_attach(g_source, NULL);
295 g_io_channel_unref(gio_channel);
298 return SYNC_AGENT_EVENT_SUCCESS;
301 EXPORT_API sync_agent_event_error_e sync_agent_stop_noti_listener()
305 inotify_rm_watch(inotify_fd, inotify_wd);
308 g_source_remove(gsource_id);
312 return SYNC_AGENT_EVENT_SUCCESS;
315 EXPORT_API sync_agent_event_error_e sync_agent_set_noti_callback(int notiType, sync_agent_noti_cb callback, void *data)
321 return event_register_noti_callback(notiType, callback, data);
324 EXPORT_API void sync_agent_free_event(sync_agent_event_data_s * event)
329 sync_agent_free_event_data(event);
335 static gboolean _agent_noti_listener(GIOChannel * p_src, GIOCondition cond, gpointer p_data)
340 struct inotify_event event = { 0, };
343 char *noti_key = (char *)p_data;
344 _DEBUG_TRACE("noti key : %s", noti_key);
346 const char *communication_path = event_get_noti_path(0);
347 _DEBUG_TRACE("Noti communication path : %s", communication_path);
349 buf_len = read(inotify_fd, (void *)&event, sizeof(event));
351 _DEBUG_ERROR("read() failed !!");
354 _DEBUG_TRACE("buffer length : %d", buf_len);
357 while (event_pos < buf_len) {
358 sync_agent_event_data_s *noti = (sync_agent_event_data_s *) calloc(1, sizeof(sync_agent_event_data_s));
360 _DEBUG_ERROR("calloc failed !!");
364 char *inbuf = (char *)calloc(EVENT_MAX_STREAM_SIZE, sizeof(char));
366 _DEBUG_ERROR("calloc failed !!");
372 event_init_event_data_iter(noti);
375 fp = fopen(communication_path, "r");
377 if (fread(inbuf, sizeof(char), EVENT_MAX_STREAM_SIZE, fp) <= 0) {
378 _DEBUG_ERROR("fread() failed !!");
384 _DEBUG_TRACE("fread() success !!");
388 _DEBUG_ERROR("fopen( %s ) failed !!", communication_path);
395 sync_agent_get_event_data_param_int(noti, ¬i_num);
396 _DEBUG_TRACE("Received Noti Number : %d", noti_num);
398 sync_agent_event_error_e error = SYNC_AGENT_EVENT_SUCCESS;;
399 __dispatch_noti(noti_num, noti, &error);
400 if (error != SYNC_AGENT_EVENT_SUCCESS) {
401 _DEBUG_ERROR("__dispatch_noti() failed !!");
403 _DEBUG_TRACE("__dispatch_noti() success !!");
406 event_pos += EVENT_SIZE + event.len;
414 static void __dispatch_noti(int noti_num, sync_agent_event_data_s * noti, sync_agent_event_error_e * error)
418 retm_if(noti == NULL, "sync_agent_event_data_s is NULL !!");
420 sync_agent_noti_cb noti_callback = event_get_noti_callback(noti_num);
421 void *additional_param = event_get_noti_callback_additional_param(noti_num);
423 if (noti_callback != NULL) {
424 noti_callback(noti, additional_param);
425 *error = SYNC_AGENT_EVENT_SUCCESS;
427 *error = SYNC_AGENT_EVENT_FAIL;