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 // enable locking of data structures in the D-Bus library for multi threading.
146 dbus_threads_init_default();
148 // Connect to the bus and check for errors
151 printf("Use specific dbus address: %s\n !", pAddress);
152 gDbusConn = dbus_connection_open(pAddress, &err);
154 if(gDbusConn != NULL)
156 if(!dbus_bus_register(gDbusConn, &err))
158 printf("dbus_bus_register() Error %s\n", err.message);
159 dbus_error_free (&err);
164 printf("Registered connection successfully !\n");
169 printf("dbus_connection_open() Error %s\n",err.message);
170 dbus_error_free(&err);
175 printf("Use default dbus bus!!!!!!\n");
176 gDbusConn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
179 // create here the dbus connection and pass to main loop
180 rval = pthread_create(&thread, NULL, run_mainloop, gDbusConn);
184 fprintf(stderr, "Server: - ERROR! pthread_create( run_mainloop ) returned: %d\n", rval);
193 static dbus_bool_t addWatch(DBusWatch *watch, void *data)
195 dbus_bool_t result = FALSE;
197 //printf("addWatch called @%08x flags: %08x enabled: %c\n", (unsigned int)watch, dbus_watch_get_flags(watch), TRUE==dbus_watch_get_enabled(watch)?'x':'-');
199 if (ARRAY_SIZE(gPollInfo.fds)>gPollInfo.nfds)
201 int flags = dbus_watch_get_flags(watch);
203 gPollInfo.watches[gPollInfo.nfds] = watch;
205 gPollInfo.fds[gPollInfo.nfds].fd = dbus_watch_get_unix_fd(watch);
207 if (TRUE==dbus_watch_get_enabled(watch))
209 if (flags&DBUS_WATCH_READABLE)
211 gPollInfo.fds[gPollInfo.nfds].events |= POLLIN;
213 if (flags&DBUS_WATCH_WRITABLE)
215 gPollInfo.fds[gPollInfo.nfds].events |= POLLOUT;
229 static void removeWatch(DBusWatch *watch, void *data)
231 printf("removeWatch called @0x%08x\n", (int)watch);
236 static void watchToggled(DBusWatch *watch, void *data)
238 printf("watchToggled called @0x%08x\n", (int)watch);
243 int mainLoop(DBusObjectPathVTable vtable, DBusObjectPathVTable vtable2,
244 DBusObjectPathVTable vtableFallback, void* userData)
248 signal(SIGTERM, sigHandler);
249 signal(SIGQUIT, sigHandler);
250 signal(SIGINT, sigHandler);
252 DBusConnection* conn = (DBusConnection*)userData;
254 dbus_error_init(&err);
256 if (dbus_error_is_set(&err))
258 printf("Connection Error (%s)\n", err.message);
259 dbus_error_free(&err);
261 else if (NULL != conn)
263 dbus_connection_set_exit_on_disconnect (conn, FALSE);
265 printf("connected as '%s'\n", dbus_bus_get_unique_name(conn));
267 if (0!=pipe(gPipefds))
269 printf("pipe() failed w/ errno %d\n", errno);
275 memset(&gPollInfo, 0 , sizeof(gPollInfo));
278 gPollInfo.fds[0].fd = gPipefds[0];
279 gPollInfo.fds[0].events = POLLIN;
281 if ( (TRUE==dbus_connection_register_object_path(conn, "/org/genivi/persistence/adminconsumer", &vtable, userData))
282 && (TRUE==dbus_connection_register_object_path(conn, "/com/contiautomotive/NodeStateManager/LifecycleConsumer", &vtable2, userData))
283 && (TRUE==dbus_connection_register_fallback(conn, "/", &vtableFallback, userData)) )
285 if (TRUE!=dbus_connection_set_watch_functions(conn, addWatch, removeWatch, watchToggled, NULL, NULL))
287 printf("dbus_connection_set_watch_functions() failed\n");
293 // minloop is running now, release mutex
294 pthread_mutex_unlock(&gDbusInitializedMtx);
297 bContinue = 0; /* assume error */
299 while (DBUS_DISPATCH_DATA_REMAINS==dbus_connection_dispatch(conn));
301 while ((-1==(ret=poll(gPollInfo.fds, gPollInfo.nfds, 500)))&&(EINTR==errno));
305 printf("poll() failed w/ errno %d\n", errno);
312 for (i=0; gPollInfo.nfds>i; ++i)
314 if (0!=gPollInfo.fds[i].revents)
316 if (gPollInfo.fds[i].fd==gPipefds[0])
318 if (0!=(gPollInfo.fds[i].revents & POLLIN))
321 while ((-1==(ret=read(gPollInfo.fds[i].fd, buf, 64)))&&(EINTR==errno));
324 printf("read() failed w/ errno %d\n", errno);
326 else if (sizeof(int)==ret)
330 case CMD_PAS_BLOCK_AND_WRITE_BACK:
331 process_block_and_write_data_back();
333 case CMD_LC_PREPARE_SHUTDOWN:
334 process_prepare_shutdown(buf[1]);
340 printf("command %d not handled!\n", buf[0]);
346 printf("read() returned %d (%s)\n", ret, buf);
353 if (0!=(gPollInfo.fds[i].revents & POLLIN))
355 flags |= DBUS_WATCH_READABLE;
357 if (0!=(gPollInfo.fds[i].revents & POLLOUT))
359 flags |= DBUS_WATCH_WRITABLE;
361 if (0!=(gPollInfo.fds[i].revents & POLLERR))
363 flags |= DBUS_WATCH_ERROR;
365 if (0!=(gPollInfo.fds[i].revents & POLLHUP))
367 flags |= DBUS_WATCH_HANGUP;
369 //printf("handle watch @0x%08x flags: %04x\n", (int)gPollInfo.watches[i], flags);
370 bContinue = dbus_watch_handle(gPollInfo.watches[i], flags);
378 while (0!=bContinue);
380 dbus_connection_unregister_object_path(conn, "/org/genivi/persistence/adminconsumer");
381 //dbus_connection_unregister_object_path(conn, "/com/");
382 dbus_connection_unregister_object_path(conn, "/");
387 dbus_connection_unref(conn);