1 /******************************************************************************
4 * Company XS Embedded GmbH
5 *****************************************************************************/
6 /******************************************************************************
7 Permission is hereby granted, free of charge, to any person obtaining
8 a copy of this software and associated documentation files (the "Software"),
9 to deal in the Software without restriction, including without limitation
10 the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 and/or sell copies of the Software, and to permit persons to whom the
12 Software is furnished to do so, subject to the following conditions:
14 The above copyright notice and this permission notice shall be included
15 in all copies or substantial portions of the Software.
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
23 OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 ******************************************************************************/
26 * @file persistence_client_library_dbus_service.c
27 * @ingroup Persistence client library
28 * @author Ingo Huerner
29 * @brief Implementation of the persistence client library dbus service.
33 //#include "persistence_client_service_dbus_service.h"
35 #include "persistence_client_library_dbus_service.h"
36 #include "persistence_client_library_lc_interface.h"
37 #include "persistence_client_library_pas_interface.h"
47 typedef struct SPollInfo
50 struct pollfd fds[10];
51 DBusWatch * watches[10];
55 /// polling information
56 static tPollInfo gPollInfo;
60 DBusConnection* gDbusConn = NULL;
63 DBusConnection* get_dbus_connection(void)
68 //------------------------------------------------------------------------
69 // debugging only until "correct" exit of main loop is possible!!!!!
70 //------------------------------------------------------------------------
72 static int endLoop = 0;
74 void sigHandler(int signo)
78 //------------------------------------------------------------------------
80 //const char* gPersDbusAdminInterface = "org.genivi.persistence.admin";
81 //const char* gPersDbusAdminPath = "/org/genivi/persistence/admin";
85 #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
88 /* function to unregister ojbect path message handler */
89 static void unregisterMessageHandler(DBusConnection *connection, void *user_data)
91 printf("unregisterObjectPath\n");
94 /* catches messages not directed to any registered object path ("garbage collector") */
95 static DBusHandlerResult handleObjectPathMessageFallback(DBusConnection * connection, DBusMessage * message, void * user_data)
97 printf("handleObjectPathMessageFallback '%s' -> '%s'\n", dbus_message_get_interface(message), dbus_message_get_member(message) );
98 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
103 static void unregisterObjectPathFallback(DBusConnection *connection, void *user_data)
105 printf("unregisterObjectPathFallback\n");
110 void* run_mainloop(void* dataPtr)
112 // lock mutex to make sure dbus main loop is running
113 pthread_mutex_lock(&gDbusInitializedMtx);
115 // persistence admin message
116 static const struct DBusObjectPathVTable vtablePersAdmin
117 = {unregisterMessageHandler, checkPersAdminMsg, NULL, };
120 static const struct DBusObjectPathVTable vtableLifecycle
121 = {unregisterMessageHandler, checkLifecycleMsg, NULL, };
124 static const struct DBusObjectPathVTable vtableFallback
125 = {unregisterObjectPathFallback, handleObjectPathMessageFallback, NULL, };
128 mainLoop(vtablePersAdmin, vtableLifecycle, vtableFallback, dataPtr);
130 printf("Exit dbus main loop!!!!\n");
137 int setup_dbus_mainloop(void)
142 const char *pAddress = getenv("PERS_CLIENT_DBUS_ADDRESS");
143 dbus_error_init(&err);
145 // Connect to the bus and check for errors
148 printf("Use specific dbus address: %s\n !", pAddress);
149 gDbusConn = dbus_connection_open(pAddress, &err);
151 if(gDbusConn != NULL)
153 if(!dbus_bus_register(gDbusConn, &err))
155 printf("dbus_bus_register() Error %s\n", err.message);
156 dbus_error_free (&err);
161 printf("Registered connection successfully !\n");
166 printf("dbus_connection_open() Error %s\n",err.message);
167 dbus_error_free(&err);
172 printf("Use default dbus bus!!!!!!\n");
173 gDbusConn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
176 // create here the dbus connection and pass to main loop
177 rval = pthread_create(&thread, NULL, run_mainloop, gDbusConn);
181 fprintf(stderr, "Server: - ERROR! pthread_create( run_mainloop ) returned: %d\n", rval);
190 static dbus_bool_t addWatch(DBusWatch *watch, void *data)
192 dbus_bool_t result = FALSE;
194 //printf("addWatch called @%08x flags: %08x enabled: %c\n", (unsigned int)watch, dbus_watch_get_flags(watch), TRUE==dbus_watch_get_enabled(watch)?'x':'-');
196 if (ARRAY_SIZE(gPollInfo.fds)>gPollInfo.nfds)
198 int flags = dbus_watch_get_flags(watch);
200 gPollInfo.watches[gPollInfo.nfds] = watch;
202 gPollInfo.fds[gPollInfo.nfds].fd = dbus_watch_get_unix_fd(watch);
204 if (TRUE==dbus_watch_get_enabled(watch))
206 if (flags&DBUS_WATCH_READABLE)
208 gPollInfo.fds[gPollInfo.nfds].events |= POLLIN;
210 if (flags&DBUS_WATCH_WRITABLE)
212 gPollInfo.fds[gPollInfo.nfds].events |= POLLOUT;
226 static void removeWatch(DBusWatch *watch, void *data)
228 printf("removeWatch called @0x%08x\n", (int)watch);
233 static void watchToggled(DBusWatch *watch, void *data)
235 printf("watchToggled called @0x%08x\n", (int)watch);
240 int mainLoop(DBusObjectPathVTable vtable, DBusObjectPathVTable vtable2,
241 DBusObjectPathVTable vtableFallback, void* userData)
245 signal(SIGTERM, sigHandler);
246 signal(SIGQUIT, sigHandler);
247 signal(SIGINT, sigHandler);
249 DBusConnection* conn = (DBusConnection*)userData;
251 dbus_error_init(&err);
253 if (dbus_error_is_set(&err))
255 printf("Connection Error (%s)\n", err.message);
256 dbus_error_free(&err);
258 else if (NULL != conn)
260 dbus_connection_set_exit_on_disconnect (conn, FALSE);
262 printf("connected as '%s'\n", dbus_bus_get_unique_name(conn));
264 if (0!=pipe(gPipefds))
266 printf("pipe() failed w/ errno %d\n", errno);
272 memset(&gPollInfo, 0 , sizeof(gPollInfo));
275 gPollInfo.fds[0].fd = gPipefds[0];
276 gPollInfo.fds[0].events = POLLIN;
278 if ( (TRUE==dbus_connection_register_object_path(conn, "/org/genivi/persistence/adminconsumer", &vtable, userData))
279 && (TRUE==dbus_connection_register_object_path(conn, "/com/contiautomotive/NodeStateManager/LifecycleConsumer", &vtable2, userData))
280 && (TRUE==dbus_connection_register_fallback(conn, "/", &vtableFallback, userData)) )
282 if (TRUE!=dbus_connection_set_watch_functions(conn, addWatch, removeWatch, watchToggled, NULL, NULL))
284 printf("dbus_connection_set_watch_functions() failed\n");
290 // minloop is running now, release mutex
291 pthread_mutex_unlock(&gDbusInitializedMtx);
294 bContinue = 0; /* assume error */
296 while (DBUS_DISPATCH_DATA_REMAINS==dbus_connection_dispatch(conn));
298 while ((-1==(ret=poll(gPollInfo.fds, gPollInfo.nfds, 500)))&&(EINTR==errno));
302 printf("poll() failed w/ errno %d\n", errno);
309 for (i=0; gPollInfo.nfds>i; ++i)
311 if (0!=gPollInfo.fds[i].revents)
313 if (gPollInfo.fds[i].fd==gPipefds[0])
315 if (0!=(gPollInfo.fds[i].revents & POLLIN))
318 while ((-1==(ret=read(gPollInfo.fds[i].fd, buf, 64)))&&(EINTR==errno));
321 printf("read() failed w/ errno %d\n", errno);
323 else if (sizeof(int)==ret)
327 case CMD_PAS_BLOCK_AND_WRITE_BACK:
328 process_block_and_write_data_back();
330 case CMD_LC_PREPARE_SHUTDOWN:
331 process_prepare_shutdown(buf[1]);
337 printf("command %d not handled!\n", buf[0]);
343 printf("read() returned %d (%s)\n", ret, buf);
350 if (0!=(gPollInfo.fds[i].revents & POLLIN))
352 flags |= DBUS_WATCH_READABLE;
354 if (0!=(gPollInfo.fds[i].revents & POLLOUT))
356 flags |= DBUS_WATCH_WRITABLE;
358 if (0!=(gPollInfo.fds[i].revents & POLLERR))
360 flags |= DBUS_WATCH_ERROR;
362 if (0!=(gPollInfo.fds[i].revents & POLLHUP))
364 flags |= DBUS_WATCH_HANGUP;
366 //printf("handle watch @0x%08x flags: %04x\n", (int)gPollInfo.watches[i], flags);
367 bContinue = dbus_watch_handle(gPollInfo.watches[i], flags);
375 while (0!=bContinue);
377 dbus_connection_unregister_object_path(conn, "/org/genivi/persistence/adminconsumer");
378 //dbus_connection_unregister_object_path(conn, "/com/");
379 dbus_connection_unregister_object_path(conn, "/");
384 dbus_connection_unref(conn);