Line data Source code
1 : /**
2 : * @file
3 : *
4 : * @brief Source for dbusrecv plugin
5 : *
6 : * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
7 : *
8 : */
9 :
10 : #ifndef HAVE_KDBCONFIG
11 : #include "kdbconfig.h"
12 : #endif
13 :
14 : #include "dbusrecv.h"
15 :
16 : #include <kdbhelper.h>
17 : #include <kdblogger.h>
18 :
19 : #include <stdio.h>
20 :
21 : /**
22 : * @see ElektraIoPluginSetBinding (kdbioplugin.h)
23 : */
24 0 : void elektraDbusRecvSetIoBinding (Plugin * handle, KeySet * parameters)
25 : {
26 0 : ELEKTRA_NOT_NULL (handle);
27 0 : ELEKTRA_NOT_NULL (parameters);
28 0 : ElektraDbusRecvPluginData * data = elektraPluginGetData (handle);
29 0 : ELEKTRA_NOT_NULL (data);
30 :
31 0 : Key * ioBindingKey = ksLookupByName (parameters, "/ioBinding", 0);
32 0 : ELEKTRA_NOT_NULL (ioBindingKey);
33 0 : ElektraIoInterface * binding = *(ElektraIoInterface **) keyValue (ioBindingKey);
34 :
35 0 : data->ioBinding = binding;
36 0 : }
37 :
38 : /**
39 : * @see ElektraNotificationOpenNotification (kdbnotificationinternal.h)
40 : */
41 0 : void elektraDbusRecvOpenNotification (Plugin * handle, KeySet * parameters)
42 : {
43 0 : ELEKTRA_NOT_NULL (handle);
44 0 : ElektraDbusRecvPluginData * pluginData = elektraPluginGetData (handle);
45 0 : ELEKTRA_NOT_NULL (pluginData);
46 :
47 : ElektraNotificationCallback callback;
48 0 : Key * callbackKey = ksLookupByName (parameters, "/callback", 0);
49 0 : ELEKTRA_NOT_NULL (callbackKey);
50 0 : callback = *(ElektraNotificationCallback *) keyValue (callbackKey);
51 :
52 : ElektraNotificationCallbackContext * context;
53 0 : Key * contextKey = ksLookupByName (parameters, "/context", 0);
54 0 : if (contextKey != NULL)
55 : {
56 0 : context = *(ElektraNotificationCallbackContext **) keyValue (contextKey);
57 : }
58 : else
59 : {
60 : context = NULL;
61 : }
62 :
63 0 : pluginData->notificationCallback = callback;
64 0 : pluginData->notificationContext = context;
65 :
66 : // init dbus connections
67 0 : if (pluginData->ioBinding && !pluginData->dbusInitialized)
68 : {
69 : int result;
70 :
71 0 : result = elektraDbusRecvSetupReceive (pluginData, DBUS_BUS_SYSTEM, elektraDbusRecvMessageHandler);
72 : if (!result)
73 : {
74 : ELEKTRA_LOG_WARNING ("setup for system bus failed!");
75 : }
76 0 : result = elektraDbusRecvSetupReceive (pluginData, DBUS_BUS_SESSION, elektraDbusRecvMessageHandler);
77 : if (!result)
78 : {
79 : ELEKTRA_LOG_WARNING ("setup for session bus failed!");
80 : }
81 :
82 0 : pluginData->dbusInitialized = 1;
83 : }
84 : else
85 : {
86 : ELEKTRA_LOG_DEBUG ("no I/O binding present. plugin in noop mode");
87 : }
88 0 : }
89 :
90 0 : void elektraDbusRecvCloseNotification (Plugin * handle, KeySet * parameters ELEKTRA_UNUSED)
91 : {
92 0 : ElektraDbusRecvPluginData * pluginData = elektraPluginGetData (handle);
93 0 : pluginData->notificationCallback = NULL;
94 0 : pluginData->notificationContext = NULL;
95 :
96 0 : if (pluginData->dbusInitialized)
97 : {
98 : int result;
99 0 : result = elektraDbusRecvTeardownReceive (pluginData, DBUS_BUS_SYSTEM, elektraDbusRecvMessageHandler);
100 : if (!result)
101 : {
102 : ELEKTRA_LOG_WARNING ("teardown for system bus failed!");
103 : }
104 0 : result = elektraDbusRecvTeardownReceive (pluginData, DBUS_BUS_SESSION, elektraDbusRecvMessageHandler);
105 : if (!result)
106 : {
107 : ELEKTRA_LOG_WARNING ("teardown for session bus failed!");
108 : }
109 :
110 0 : pluginData->dbusInitialized = 0;
111 : }
112 0 : }
113 :
114 : /**
115 : * @internal
116 : * Process D-Bus messages and check for Elektra's signal messages.
117 : *
118 : * Only KeyChanged and KeyAdded are processed.
119 : *
120 : * @param connection D-Bus connection
121 : * @param message message
122 : * @param data plugin data
123 : * @return handler result
124 : */
125 0 : DBusHandlerResult elektraDbusRecvMessageHandler (DBusConnection * connection ELEKTRA_UNUSED, DBusMessage * message, void * data)
126 : {
127 0 : char * interface = "org.libelektra";
128 :
129 0 : int processMessage = dbus_message_is_signal (message, interface, "Commit") ||
130 0 : dbus_message_is_signal (message, interface, "KeyAdded") ||
131 0 : dbus_message_is_signal (message, interface, "KeyChanged");
132 0 : if (processMessage)
133 : {
134 : char * keyName;
135 : DBusError error;
136 0 : dbus_error_init (&error);
137 :
138 : // read key name from message
139 0 : dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &keyName, DBUS_TYPE_INVALID);
140 0 : if (dbus_error_is_set (&error))
141 : {
142 : ELEKTRA_LOG_WARNING ("Failed to read message: %s", error.message);
143 : }
144 : else
145 : {
146 0 : Key * changed = keyNew (keyName, KEY_END);
147 0 : ElektraDbusRecvPluginData * pluginData = (ElektraDbusRecvPluginData *) data;
148 0 : ELEKTRA_NOT_NULL (pluginData);
149 0 : pluginData->notificationCallback (changed, pluginData->notificationContext);
150 : }
151 :
152 0 : dbus_error_free (&error);
153 : return DBUS_HANDLER_RESULT_HANDLED;
154 : }
155 : return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
156 : }
157 :
158 20 : int elektraDbusRecvOpen (Plugin * handle, Key * errorKey ELEKTRA_UNUSED)
159 : {
160 20 : ElektraDbusRecvPluginData * data = (ElektraDbusRecvPluginData *) elektraPluginGetData (handle);
161 20 : if (!data)
162 : {
163 20 : data = elektraMalloc (sizeof (*data));
164 20 : data->ioBinding = NULL;
165 20 : data->notificationCallback = NULL;
166 20 : data->dbusInitialized = 0;
167 20 : data->systemBus = NULL;
168 20 : data->sessionBus = NULL;
169 : }
170 20 : elektraPluginSetData (handle, data);
171 :
172 20 : return 1; /* success */
173 : }
174 :
175 20 : int elektraDbusRecvGet (Plugin * handle ELEKTRA_UNUSED, KeySet * returned, Key * parentKey)
176 : {
177 20 : if (!strcmp (keyName (parentKey), "system/elektra/modules/dbusrecv"))
178 : {
179 20 : KeySet * contract = ksNew (
180 : 30, keyNew ("system/elektra/modules/dbusrecv", KEY_VALUE, "dbusrecv plugin waits for your orders", KEY_END),
181 : keyNew ("system/elektra/modules/dbusrecv/exports", KEY_END),
182 : keyNew ("system/elektra/modules/dbusrecv/exports/open", KEY_FUNC, elektraDbusRecvOpen, KEY_END),
183 : keyNew ("system/elektra/modules/dbusrecv/exports/get", KEY_FUNC, elektraDbusRecvGet, KEY_END),
184 : keyNew ("system/elektra/modules/dbusrecv/exports/close", KEY_FUNC, elektraDbusRecvClose, KEY_END),
185 : keyNew ("system/elektra/modules/dbusrecv/exports/setIoBinding", KEY_FUNC, elektraDbusRecvSetIoBinding, KEY_END),
186 : keyNew ("system/elektra/modules/dbusrecv/exports/openNotification", KEY_FUNC, elektraDbusRecvOpenNotification,
187 : KEY_END),
188 : keyNew ("system/elektra/modules/dbusrecv/exports/closeNotification", KEY_FUNC, elektraDbusRecvCloseNotification,
189 : KEY_END),
190 : #include ELEKTRA_README
191 : keyNew ("system/elektra/modules/dbusrecv/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END);
192 20 : ksAppend (returned, contract);
193 20 : ksDel (contract);
194 :
195 20 : return 1; /* success */
196 : }
197 :
198 : return 1; /* success */
199 : }
200 :
201 20 : int elektraDbusRecvClose (Plugin * handle, Key * parentKey ELEKTRA_UNUSED)
202 : {
203 20 : ElektraDbusRecvPluginData * pluginData = elektraPluginGetData (handle);
204 20 : if (pluginData == NULL)
205 : {
206 : return 1;
207 : }
208 :
209 20 : if (pluginData->systemBus)
210 : {
211 0 : elektraIoAdapterDbusCleanup (pluginData->systemBusAdapter);
212 0 : dbus_connection_close (pluginData->systemBus);
213 0 : dbus_connection_unref (pluginData->systemBus);
214 0 : pluginData->systemBus = NULL;
215 : }
216 20 : if (pluginData->sessionBus)
217 : {
218 0 : elektraIoAdapterDbusCleanup (pluginData->sessionBusAdapter);
219 0 : dbus_connection_close (pluginData->sessionBus);
220 0 : dbus_connection_unref (pluginData->sessionBus);
221 0 : pluginData->sessionBus = NULL;
222 : }
223 :
224 20 : elektraFree (pluginData);
225 20 : elektraPluginSetData (handle, NULL);
226 :
227 20 : return 1; /* success */
228 : }
229 :
230 20 : Plugin * ELEKTRA_PLUGIN_EXPORT
231 : {
232 : // clang-format off
233 20 : return elektraPluginExport("dbusrecv",
234 : ELEKTRA_PLUGIN_OPEN, &elektraDbusRecvOpen,
235 : ELEKTRA_PLUGIN_GET, &elektraDbusRecvGet,
236 : ELEKTRA_PLUGIN_CLOSE, &elektraDbusRecvClose,
237 : ELEKTRA_PLUGIN_END);
238 : }
|