diff options
Diffstat (limited to 'src/lib/common/gnunet_dbus_lib_interface.c')
-rw-r--r-- | src/lib/common/gnunet_dbus_lib_interface.c | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/src/lib/common/gnunet_dbus_lib_interface.c b/src/lib/common/gnunet_dbus_lib_interface.c new file mode 100644 index 0000000..bbc3467 --- /dev/null +++ b/src/lib/common/gnunet_dbus_lib_interface.c | |||
@@ -0,0 +1,275 @@ | |||
1 | #include "config.h" | ||
2 | |||
3 | #include <dbus/dbus.h> | ||
4 | |||
5 | #include <gnunet/platform.h> | ||
6 | #include <gnunet/gnunet_common.h> | ||
7 | #include <gnunet/gnunet_container_lib.h> | ||
8 | |||
9 | #include "gnunet_dbus_lib.h" | ||
10 | |||
11 | #define LOG(kind, ...) GNUNET_log_from (kind, "dbus-interface", __VA_ARGS__) | ||
12 | |||
13 | struct GNUNET_DBUS_Interface | ||
14 | { | ||
15 | struct GNUNET_DBUS_MethodIterator *methods_front; | ||
16 | struct GNUNET_DBUS_MethodIterator *methods_back; | ||
17 | |||
18 | struct GNUNET_DBUS_SignalIterator *signals_front; | ||
19 | struct GNUNET_DBUS_SignalIterator *signals_back; | ||
20 | |||
21 | char *name; | ||
22 | unsigned ref_count; | ||
23 | }; | ||
24 | |||
25 | struct GNUNET_DBUS_Interface * | ||
26 | GNUNET_DBUS_interface_create ( | ||
27 | const char *name) | ||
28 | { | ||
29 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating interface %s\n", name); | ||
30 | |||
31 | struct GNUNET_DBUS_Interface *interface = GNUNET_new (struct GNUNET_DBUS_Interface); | ||
32 | |||
33 | interface->methods_front = NULL; | ||
34 | interface->methods_back = NULL; | ||
35 | interface->name = GNUNET_strdup (name); | ||
36 | interface->ref_count = 1; | ||
37 | |||
38 | return interface; | ||
39 | }; | ||
40 | |||
41 | void | ||
42 | GNUNET_DBUS_interface_ref ( | ||
43 | struct GNUNET_DBUS_Interface *interface) | ||
44 | { | ||
45 | interface->ref_count++; | ||
46 | }; | ||
47 | |||
48 | void | ||
49 | GNUNET_DBUS_interface_unref ( | ||
50 | struct GNUNET_DBUS_Interface *interface) | ||
51 | { | ||
52 | if (interface->ref_count == 0) | ||
53 | { | ||
54 | LOG (GNUNET_ERROR_TYPE_ERROR, "Tried to unreference interface with ref count 0\n"); | ||
55 | GNUNET_abort_ (); | ||
56 | }; | ||
57 | if (0 == --(interface->ref_count)) | ||
58 | { | ||
59 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying interface %s\n", interface->name); | ||
60 | |||
61 | struct GNUNET_DBUS_MethodIterator *methods_iter = interface->methods_front; | ||
62 | while (methods_iter) | ||
63 | { | ||
64 | struct GNUNET_DBUS_MethodIterator *next = methods_iter->next; | ||
65 | GNUNET_DBUS_method_unref (methods_iter->method); | ||
66 | GNUNET_free (methods_iter); | ||
67 | methods_iter = next; | ||
68 | }; | ||
69 | |||
70 | GNUNET_free (interface->name); | ||
71 | GNUNET_free (interface); | ||
72 | } | ||
73 | }; | ||
74 | |||
75 | void | ||
76 | GNUNET_DBUS_interface_add_method ( | ||
77 | struct GNUNET_DBUS_Interface *interface, | ||
78 | struct GNUNET_DBUS_Method *method) | ||
79 | { | ||
80 | struct GNUNET_DBUS_MethodIterator *meth_it = GNUNET_new (struct GNUNET_DBUS_MethodIterator); | ||
81 | meth_it->method = method; | ||
82 | GNUNET_DBUS_method_ref (method); | ||
83 | |||
84 | GNUNET_CONTAINER_DLL_insert (interface->methods_front, | ||
85 | interface->methods_back, | ||
86 | meth_it); | ||
87 | }; | ||
88 | |||
89 | void | ||
90 | GNUNET_DBUS_interface_add_signal ( | ||
91 | struct GNUNET_DBUS_Interface *interface, | ||
92 | struct GNUNET_DBUS_Signal *signal) | ||
93 | { | ||
94 | struct GNUNET_DBUS_SignalIterator *sig_it = GNUNET_new (struct GNUNET_DBUS_SignalIterator); | ||
95 | sig_it->signal = signal; | ||
96 | GNUNET_DBUS_signal_ref (signal); | ||
97 | |||
98 | GNUNET_CONTAINER_DLL_insert (interface->signals_front, | ||
99 | interface->signals_back, | ||
100 | sig_it); | ||
101 | }; | ||
102 | |||
103 | const char * | ||
104 | GNUNET_DBUS_interface_get_name ( | ||
105 | const struct GNUNET_DBUS_Interface *interface) | ||
106 | { | ||
107 | return interface->name; | ||
108 | }; | ||
109 | |||
110 | const struct GNUNET_DBUS_MethodIterator * | ||
111 | GNUNET_DBUS_interface_iterate_methods ( | ||
112 | const struct GNUNET_DBUS_Interface *interface) | ||
113 | { | ||
114 | return interface->methods_front; | ||
115 | }; | ||
116 | |||
117 | const struct GNUNET_DBUS_SignalIterator * | ||
118 | GNUNET_DBUS_interface_iterate_signals ( | ||
119 | const struct GNUNET_DBUS_Interface *interface) | ||
120 | { | ||
121 | return interface->signals_front; | ||
122 | } | ||
123 | |||
124 | static void | ||
125 | introspectable_introspect ( | ||
126 | struct GNUNET_DBUS_MethodContext *mc) | ||
127 | { | ||
128 | char *data = NULL; | ||
129 | char *new_data = NULL; | ||
130 | |||
131 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Introspecting\n"); | ||
132 | struct GNUNET_DBUS_Object *object = mc->object; | ||
133 | |||
134 | GNUNET_asprintf (&data, "%s", DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE); | ||
135 | GNUNET_asprintf (&new_data, "%s<node>\n", data); | ||
136 | GNUNET_free (data); data = new_data; | ||
137 | |||
138 | const struct GNUNET_DBUS_InterfaceIterator *int_it = GNUNET_DBUS_object_iterate_interfaces (object); | ||
139 | while (int_it) | ||
140 | { | ||
141 | struct GNUNET_DBUS_Interface *interface = int_it->interface; | ||
142 | const char *interface_name = GNUNET_DBUS_interface_get_name (interface); | ||
143 | GNUNET_asprintf (&new_data, "%s <interface name='%s'>\n", data, interface_name); | ||
144 | GNUNET_free (data); data = new_data; | ||
145 | const struct GNUNET_DBUS_MethodIterator *meth_it = GNUNET_DBUS_interface_iterate_methods (interface); | ||
146 | while (meth_it) | ||
147 | { | ||
148 | struct GNUNET_DBUS_Method *method = meth_it->method; | ||
149 | const char *method_name = GNUNET_DBUS_method_get_name (method); | ||
150 | GNUNET_asprintf (&new_data, "%s <method name='%s'>\n", data, method_name); | ||
151 | GNUNET_free (data); data = new_data; | ||
152 | const struct GNUNET_DBUS_ArgIterator *arg_it = GNUNET_DBUS_method_iterate_args (method); | ||
153 | while (arg_it) | ||
154 | { | ||
155 | struct GNUNET_DBUS_Arg *arg = arg_it->arg; | ||
156 | const char *arg_name = GNUNET_DBUS_arg_get_name (arg); | ||
157 | const char *signature = GNUNET_DBUS_arg_get_signature (arg); | ||
158 | GNUNET_asprintf ( | ||
159 | &new_data, | ||
160 | "%s <arg name='%s' type='%s' direction='in'/>\n", | ||
161 | data, | ||
162 | arg_name, | ||
163 | signature); | ||
164 | GNUNET_free (data); data = new_data; | ||
165 | arg_it = arg_it->next; | ||
166 | }; | ||
167 | |||
168 | arg_it = GNUNET_DBUS_method_iterate_return_args (method); | ||
169 | while (arg_it) | ||
170 | { | ||
171 | struct GNUNET_DBUS_Arg *arg = arg_it->arg; | ||
172 | const char *arg_name = GNUNET_DBUS_arg_get_name (arg); | ||
173 | const char *signature = GNUNET_DBUS_arg_get_signature (arg); | ||
174 | GNUNET_asprintf ( | ||
175 | &new_data, | ||
176 | "%s <arg name='%s' type='%s' direction='out'/>\n", | ||
177 | data, | ||
178 | arg_name, | ||
179 | signature); | ||
180 | GNUNET_free (data); data = new_data; | ||
181 | arg_it = arg_it->next; | ||
182 | }; | ||
183 | GNUNET_asprintf (&new_data, "%s </method>\n", data); | ||
184 | GNUNET_free (data); data = new_data; | ||
185 | meth_it = meth_it->next; | ||
186 | }; | ||
187 | const struct GNUNET_DBUS_SignalIterator *sig_it = GNUNET_DBUS_interface_iterate_signals (interface); | ||
188 | while (sig_it) | ||
189 | { | ||
190 | struct GNUNET_DBUS_Signal *signal = sig_it->signal; | ||
191 | const char *signal_name = GNUNET_DBUS_signal_get_name (signal); | ||
192 | GNUNET_asprintf (&new_data, "%s <signal name='%s'>\n", data, signal_name); | ||
193 | GNUNET_free (data); data = new_data; | ||
194 | const struct GNUNET_DBUS_ArgIterator *arg_it = GNUNET_DBUS_signal_iterate_args (signal); | ||
195 | while (arg_it) | ||
196 | { | ||
197 | struct GNUNET_DBUS_Arg *arg = arg_it->arg; | ||
198 | const char *arg_name = GNUNET_DBUS_arg_get_name (arg); | ||
199 | const char *signature = GNUNET_DBUS_arg_get_signature (arg); | ||
200 | GNUNET_asprintf ( | ||
201 | &new_data, | ||
202 | "%s <arg name='%s' type='%s'/>\n", | ||
203 | data, | ||
204 | arg_name, | ||
205 | signature); | ||
206 | GNUNET_free (data); data = new_data; | ||
207 | arg_it = arg_it->next; | ||
208 | } | ||
209 | GNUNET_asprintf (&new_data, "%s </signal>\n", data); | ||
210 | GNUNET_free (data); data = new_data; | ||
211 | sig_it = sig_it->next; | ||
212 | }; | ||
213 | GNUNET_asprintf (&new_data, "%s </interface>\n", data); | ||
214 | GNUNET_free (data); data = new_data; | ||
215 | int_it = int_it->next; | ||
216 | }; | ||
217 | const struct GNUNET_DBUS_ObjectIterator *obj_it = GNUNET_DBUS_object_iterate_subobjects (object); | ||
218 | while (obj_it) | ||
219 | { | ||
220 | const char *obj_name = GNUNET_DBUS_object_get_name (obj_it->object); | ||
221 | GNUNET_asprintf (&new_data, "%s <node name='%s'/>\n", data, obj_name); | ||
222 | GNUNET_free (data); data = new_data; | ||
223 | obj_it = obj_it->next; | ||
224 | } | ||
225 | GNUNET_asprintf (&new_data, "%s</node>\n", data); | ||
226 | GNUNET_free (data); data = new_data; | ||
227 | |||
228 | DBusMessage *reply = GNUNET_DBUS_method_context_create_reply (mc); | ||
229 | DBusMessageIter reply_iter; | ||
230 | dbus_message_iter_init_append (reply, &reply_iter); | ||
231 | GNUNET_DBUS_push_string (reply, &reply_iter, (const char *const *)&data); | ||
232 | GNUNET_DBUS_method_context_send_reply (mc, reply); | ||
233 | GNUNET_free (data); | ||
234 | }; | ||
235 | |||
236 | struct GNUNET_DBUS_Interface *interface_introspectable; | ||
237 | |||
238 | static void construct_interface_introspectable () | ||
239 | __attribute__((constructor)); | ||
240 | |||
241 | static void destruct_interface_introspectable () | ||
242 | __attribute__((destructor)); | ||
243 | |||
244 | static void construct_interface_introspectable () | ||
245 | { | ||
246 | interface_introspectable = GNUNET_DBUS_interface_create ("org.freedesktop.DBus.Introspectable"); | ||
247 | struct GNUNET_DBUS_Method *introspect = GNUNET_DBUS_method_create ("Introspect", introspectable_introspect); | ||
248 | GNUNET_DBUS_method_add_return_arg (introspect, "data", GNUNET_DBUS_SIGNATURE_STRING); | ||
249 | GNUNET_DBUS_interface_add_method (interface_introspectable, introspect); | ||
250 | } | ||
251 | |||
252 | static void destruct_interface_introspectable () | ||
253 | { | ||
254 | GNUNET_DBUS_interface_unref (interface_introspectable); | ||
255 | } | ||
256 | |||
257 | struct GNUNET_DBUS_Interface * | ||
258 | GNUNET_DBUS_interface_introspectable () | ||
259 | { | ||
260 | return interface_introspectable; | ||
261 | }; | ||
262 | |||
263 | const struct GNUNET_DBUS_InterfaceIterator * | ||
264 | GNUNET_DBUS_interface_find ( | ||
265 | const struct GNUNET_DBUS_InterfaceIterator *int_it, | ||
266 | const char *name) | ||
267 | { | ||
268 | for (; int_it; int_it = int_it->next) | ||
269 | { | ||
270 | if (! strcmp (name, int_it->interface->name)) | ||
271 | return int_it; | ||
272 | } | ||
273 | return NULL; | ||
274 | } | ||
275 | |||