1 /******************************************************************************
4 * Company XS Embedded GmbH
5 *****************************************************************************/
6 /******************************************************************************
7 * This Source Code Form is subject to the terms of the
8 * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed
9 * with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 ******************************************************************************/
12 * @file persistence_client_library_dbus_service.c
13 * @ingroup Persistence client library
14 * @author Ingo Huerner
15 * @brief Implementation of the persistence client library dbus service.
19 //#include "persistence_client_service_dbus_service.h"
21 #include "persistence_client_library_dbus_service.h"
22 #include "persistence_client_library_lc_interface.h"
23 #include "persistence_client_library_pas_interface.h"
32 pthread_mutex_t gDbusInitializedMtx = PTHREAD_MUTEX_INITIALIZER;
33 pthread_cond_t gDbusInitializedCond = PTHREAD_COND_INITIALIZER;
36 typedef struct SPollInfo
39 struct pollfd fds[10];
40 DBusWatch * watches[10];
44 /// polling information
45 static tPollInfo gPollInfo;
49 DBusConnection* gDbusConn = NULL;
52 DBusConnection* get_dbus_connection(void)
57 //------------------------------------------------------------------------
58 // debugging only until "correct" exit of main loop is possible!!!!!
59 //------------------------------------------------------------------------
61 static int endLoop = 0;
63 void sigHandler(int signo)
67 //------------------------------------------------------------------------
71 #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
74 /* function to unregister ojbect path message handler */
75 static void unregisterMessageHandler(DBusConnection *connection, void *user_data)
77 printf("unregisterObjectPath\n");
80 /* catches messages not directed to any registered object path ("garbage collector") */
81 static DBusHandlerResult handleObjectPathMessageFallback(DBusConnection * connection, DBusMessage * message, void * user_data)
83 DBusHandlerResult result = DBUS_HANDLER_RESULT_HANDLED;
85 printf("handleObjectPathMessageFallback Object: '%s' -> Interface: '%s' -> Message: '%s'\n",
86 dbus_message_get_sender(message), dbus_message_get_interface(message), dbus_message_get_member(message) );
88 // org.genivi.persistence.admin S I G N A L
89 if((0==strcmp("org.genivi.persistence.admin", dbus_message_get_interface(message))))
91 // printf("checkPersAdminSignalInterface '%s' -> '%s'\n", dbus_message_get_interface(message), dbus_message_get_member(message));
92 if(dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
94 printf(" checkPersAdminSignal signal\n");
95 if((0==strcmp("PersistenceModeChanged", dbus_message_get_member(message))))
97 printf(" checkPersAdminSignal message\n");
98 // to do handle signal
99 result = signal_persModeChange(connection, message);
103 printf("handleObjectPathMessageFallback -> unknown signal '%s'\n", dbus_message_get_interface(message));
108 // org.genivi.persistence.admin P R O P E R T Y
109 else if((0==strcmp("org.freedesktop.DBus.Properties", dbus_message_get_interface(message))))
111 if(dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
113 if((0==strcmp("EggDBusChanged", dbus_message_get_member(message))))
115 DBusMessageIter array;
116 DBusMessageIter dict;
117 DBusMessageIter variant;
119 char* dictString = NULL;
122 dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, 0, &dict);
123 dbus_message_iter_get_basic(&dict, &dictString);
125 dbus_message_iter_open_container(&dict,DBUS_TYPE_VARIANT, NULL, &variant);
126 dbus_message_iter_get_basic(&dict, &value);
128 dbus_message_iter_close_container(&dict, &variant);
129 dbus_message_iter_close_container(&array, &dict);
131 printf("handleObjectPathMessageFallback ==> value: %d \n", value);
132 // to do handle signal
133 result = DBUS_HANDLER_RESULT_HANDLED;
137 printf("handleObjectPathMessageFallback -> unknown property '%s'\n", dbus_message_get_interface(message));
142 printf("handleObjectPathMessageFallback -> not a signal '%s'\n", dbus_message_get_member(message));
151 static void unregisterObjectPathFallback(DBusConnection *connection, void *user_data)
153 printf("unregisterObjectPathFallback\n");
158 void* run_mainloop(void* dataPtr)
160 // persistence admin message
161 static const struct DBusObjectPathVTable vtablePersAdmin
162 = {unregisterMessageHandler, checkPersAdminMsg, NULL, };
165 static const struct DBusObjectPathVTable vtableLifecycle
166 = {unregisterMessageHandler, checkLifecycleMsg, NULL, };
169 static const struct DBusObjectPathVTable vtableFallback
170 = {unregisterObjectPathFallback, handleObjectPathMessageFallback, NULL, };
173 mainLoop(vtablePersAdmin, vtableLifecycle, vtableFallback, dataPtr);
175 printf("Exit dbus main loop!!!!\n");
182 int setup_dbus_mainloop(void)
187 const char *pAddress = getenv("PERS_CLIENT_DBUS_ADDRESS");
188 dbus_error_init(&err);
190 // enable locking of data structures in the D-Bus library for multi threading.
191 dbus_threads_init_default();
193 // Connect to the bus and check for errors
196 printf("Use specific dbus address: %s\n !", pAddress);
197 gDbusConn = dbus_connection_open(pAddress, &err);
199 if(gDbusConn != NULL)
201 if(!dbus_bus_register(gDbusConn, &err))
203 printf("dbus_bus_register() Error %s\n", err.message);
204 dbus_error_free (&err);
209 printf("Registered connection successfully !\n");
214 printf("dbus_connection_open() Error %s\n",err.message);
215 dbus_error_free(&err);
220 printf("Use default dbus bus!!!!!!\n");
221 gDbusConn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
224 // wain until dbus main loop has been setup and running
225 pthread_mutex_lock(&gDbusInitializedMtx);
227 // create here the dbus connection and pass to main loop
228 rval = pthread_create(&thread, NULL, run_mainloop, gDbusConn);
231 fprintf(stderr, "Server: - ERROR! pthread_create( run_mainloop ) returned: %d\n", rval);
234 // wait for condition variable
235 pthread_cond_wait(&gDbusInitializedCond, &gDbusInitializedMtx);
237 pthread_mutex_unlock(&gDbusInitializedMtx);
245 static dbus_bool_t addWatch(DBusWatch *watch, void *data)
247 dbus_bool_t result = FALSE;
249 //printf("addWatch called @%08x flags: %08x enabled: %c\n", (unsigned int)watch, dbus_watch_get_flags(watch), TRUE==dbus_watch_get_enabled(watch)?'x':'-');
251 if (ARRAY_SIZE(gPollInfo.fds)>gPollInfo.nfds)
253 int flags = dbus_watch_get_flags(watch);
255 gPollInfo.watches[gPollInfo.nfds] = watch;
257 gPollInfo.fds[gPollInfo.nfds].fd = dbus_watch_get_unix_fd(watch);
259 if (TRUE==dbus_watch_get_enabled(watch))
261 if (flags&DBUS_WATCH_READABLE)
263 gPollInfo.fds[gPollInfo.nfds].events |= POLLIN;
265 if (flags&DBUS_WATCH_WRITABLE)
267 gPollInfo.fds[gPollInfo.nfds].events |= POLLOUT;
281 static void removeWatch(DBusWatch *watch, void *data)
283 printf("removeWatch called @0x%08x\n", (int)watch);
288 static void watchToggled(DBusWatch *watch, void *data)
290 printf("watchToggled called @0x%08x\n", (int)watch);
295 int mainLoop(DBusObjectPathVTable vtable, DBusObjectPathVTable vtable2,
296 DBusObjectPathVTable vtableFallback, void* userData)
299 // lock mutex to make sure dbus main loop is running
300 pthread_mutex_lock(&gDbusInitializedMtx);
302 signal(SIGTERM, sigHandler);
303 signal(SIGQUIT, sigHandler);
304 signal(SIGINT, sigHandler);
306 DBusConnection* conn = (DBusConnection*)userData;
307 dbus_error_init(&err);
309 if (dbus_error_is_set(&err))
311 printf("Connection Error (%s)\n", err.message);
312 dbus_error_free(&err);
314 else if (NULL != conn)
316 dbus_connection_set_exit_on_disconnect (conn, FALSE);
317 printf("connected as '%s'\n", dbus_bus_get_unique_name(conn));
318 if (0!=pipe(gPipefds))
320 printf("pipe() failed w/ errno %d\n", errno);
326 memset(&gPollInfo, 0 , sizeof(gPollInfo));
329 gPollInfo.fds[0].fd = gPipefds[0];
330 gPollInfo.fds[0].events = POLLIN;
332 dbus_bus_add_match(conn, "type='signal',interface='org.genivi.persistence.admin',member='PersistenceModeChanged',path='/org/genivi/persistence/admin'", &err);
334 // register for messages
335 if ( (TRUE==dbus_connection_register_object_path(conn, "/org/genivi/persistence/adminconsumer", &vtable, userData))
336 && (TRUE==dbus_connection_register_object_path(conn, "/com/contiautomotive/NodeStateManager/LifecycleConsumer", &vtable2, userData))
337 && (TRUE==dbus_connection_register_fallback(conn, "/", &vtableFallback, userData)) )
339 if (TRUE!=dbus_connection_set_watch_functions(conn, addWatch, removeWatch, watchToggled, NULL, NULL))
341 printf("dbus_connection_set_watch_functions() failed\n");
347 pthread_cond_signal(&gDbusInitializedCond);
348 pthread_mutex_unlock(&gDbusInitializedMtx);
351 bContinue = 0; /* assume error */
353 while(DBUS_DISPATCH_DATA_REMAINS==dbus_connection_dispatch(conn));
355 while((-1==(ret=poll(gPollInfo.fds, gPollInfo.nfds, 500)))&&(EINTR==errno));
359 printf("poll() failed w/ errno %d\n", errno);
366 for (i=0; gPollInfo.nfds>i; ++i)
368 if (0!=gPollInfo.fds[i].revents)
370 if (gPollInfo.fds[i].fd==gPipefds[0])
372 if (0!=(gPollInfo.fds[i].revents & POLLIN))
375 while ((-1==(ret=read(gPollInfo.fds[i].fd, buf, 64)))&&(EINTR==errno));
378 printf("read() failed w/ errno %d\n", errno);
380 else if (sizeof(int)==ret)
384 case CMD_PAS_BLOCK_AND_WRITE_BACK:
385 process_block_and_write_data_back();
387 case CMD_LC_PREPARE_SHUTDOWN:
388 process_prepare_shutdown(buf[1]);
394 printf("command %d not handled!\n", buf[0]);
400 printf("read() returned %d (%s)\n", ret, buf);
407 if (0!=(gPollInfo.fds[i].revents & POLLIN))
409 flags |= DBUS_WATCH_READABLE;
411 if (0!=(gPollInfo.fds[i].revents & POLLOUT))
413 flags |= DBUS_WATCH_WRITABLE;
415 if (0!=(gPollInfo.fds[i].revents & POLLERR))
417 flags |= DBUS_WATCH_ERROR;
419 if (0!=(gPollInfo.fds[i].revents & POLLHUP))
421 flags |= DBUS_WATCH_HANGUP;
423 //printf("handle watch @0x%08x flags: %04x\n", (int)gPollInfo.watches[i], flags);
424 bContinue = dbus_watch_handle(gPollInfo.watches[i], flags);
432 while (0!=bContinue);
434 dbus_connection_unregister_object_path(conn, "/org/genivi/persistence/adminconsumer");
435 dbus_connection_unregister_object_path(conn, "/com/contiautomotive/NodeStateManager/LifecycleConsumer");
436 dbus_connection_unregister_object_path(conn, "/");
441 dbus_connection_unref(conn);
445 pthread_cond_signal(&gDbusInitializedCond);
446 pthread_mutex_unlock(&gDbusInitializedMtx);