]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/test-bus-chat.c
bus: when parsing enforce maximum container depth
[thirdparty/systemd.git] / src / libsystemd-bus / test-bus-chat.c
CommitLineData
89ffcd2a
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <assert.h>
23#include <stdlib.h>
24#include <pthread.h>
e3017af9 25#include <unistd.h>
89ffcd2a
LP
26
27#include "log.h"
28#include "util.h"
29
30#include "sd-bus.h"
31#include "bus-message.h"
e3017af9 32#include "bus-error.h"
89ffcd2a
LP
33
34static int server_init(sd_bus **_bus) {
35 sd_bus *bus = NULL;
d728d708 36 sd_id128_t id;
89ffcd2a
LP
37 int r;
38
39 assert(_bus);
40
41 r = sd_bus_open_user(&bus);
42 if (r < 0) {
43 log_error("Failed to connect to user bus: %s", strerror(-r));
44 goto fail;
45 }
46
d728d708
LP
47 r = sd_bus_get_peer(bus, &id);
48 if (r < 0) {
49 log_error("Failed to get peer ID: %s", strerror(-r));
50 goto fail;
51 }
52
53 log_info("Peer ID is " SD_ID128_FORMAT_STR ".", SD_ID128_FORMAT_VAL(id));
54 log_info("Can send file handles: %i", sd_bus_can_send(bus, 'h'));
55 log_info("Unique ID: %s", strna(sd_bus_get_unique_name(bus)));
56
89ffcd2a
LP
57 r = sd_bus_request_name(bus, "org.freedesktop.systemd.test", 0);
58 if (r < 0) {
59 log_error("Failed to acquire name: %s", strerror(-r));
60 goto fail;
61 }
62
63 *_bus = bus;
64 return 0;
65
66fail:
67 if (bus)
68 sd_bus_unref(bus);
69
70 return r;
71}
72
e3017af9 73static int server(sd_bus *bus) {
89ffcd2a 74 int r;
e3017af9 75 bool client1_gone = false, client2_gone = false;
89ffcd2a 76
e3017af9 77 while (!client1_gone || !client2_gone) {
89ffcd2a
LP
78 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
79
80 r = sd_bus_process(bus, &m);
81 if (r < 0) {
82 log_error("Failed to process requests: %s", strerror(-r));
83 goto fail;
84 }
e3017af9 85
89ffcd2a
LP
86 if (r == 0) {
87 r = sd_bus_wait(bus, (uint64_t) -1);
88 if (r < 0) {
89 log_error("Failed to wait: %s", strerror(-r));
90 goto fail;
91 }
92
93 continue;
94 }
95
e3017af9
LP
96 if (!m)
97 continue;
98
89ffcd2a
LP
99 log_info("Got message! %s", strna(sd_bus_message_get_member(m)));
100 /* bus_message_dump(m); */
101 /* sd_bus_message_rewind(m, true); */
102
103 if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "LowerCase")) {
104 const char *hello;
105 _cleanup_free_ char *lowercase = NULL;
106
107 r = sd_bus_message_read(m, "s", &hello);
108 if (r < 0) {
109 log_error("Failed to get parameter: %s", strerror(-r));
110 goto fail;
111 }
112
113 r = sd_bus_message_new_method_return(bus, m, &reply);
114 if (r < 0) {
115 log_error("Failed to allocate return: %s", strerror(-r));
116 goto fail;
117 }
118
119 lowercase = strdup(hello);
120 if (!lowercase) {
121 r = log_oom();
122 goto fail;
123 }
124
125 ascii_strlower(lowercase);
126
127 r = sd_bus_message_append(reply, "s", lowercase);
128 if (r < 0) {
129 log_error("Failed to append message: %s", strerror(-r));
130 goto fail;
131 }
e3017af9
LP
132 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient1")) {
133
134 r = sd_bus_message_new_method_return(bus, m, &reply);
135 if (r < 0) {
136 log_error("Failed to allocate return: %s", strerror(-r));
137 goto fail;
138 }
139
140 client1_gone = true;
141 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient2")) {
142
143 r = sd_bus_message_new_method_return(bus, m, &reply);
144 if (r < 0) {
145 log_error("Failed to allocate return: %s", strerror(-r));
146 goto fail;
147 }
148
149 client2_gone = true;
150 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Slow")) {
151
152 r = sd_bus_message_new_method_return(bus, m, &reply);
153 if (r < 0) {
154 log_error("Failed to allocate return: %s", strerror(-r));
155 goto fail;
156 }
157
158 sleep(1);
159 } else if (sd_bus_message_is_method_call(m, NULL, NULL)) {
89ffcd2a
LP
160 const sd_bus_error e = SD_BUS_ERROR_INIT_CONST("org.freedesktop.DBus.Error.UnknownMethod", "Unknown method.");
161
162 r = sd_bus_message_new_method_error(bus, m, &e, &reply);
163 if (r < 0) {
164 log_error("Failed to allocate return: %s", strerror(-r));
165 goto fail;
166 }
167 }
168
169 if (reply) {
170 r = sd_bus_send(bus, reply, NULL);
171 if (r < 0) {
172 log_error("Failed to send reply: %s", strerror(-r));
173 goto fail;
174 }
e3017af9
LP
175
176 /* log_info("Sent"); */
177 /* bus_message_dump(reply); */
178 /* sd_bus_message_rewind(reply, true); */
89ffcd2a
LP
179 }
180 }
181
182 r = 0;
183
184fail:
e3017af9
LP
185 if (bus) {
186 sd_bus_flush(bus);
89ffcd2a 187 sd_bus_unref(bus);
e3017af9 188 }
89ffcd2a 189
e3017af9 190 return r;
89ffcd2a
LP
191}
192
e3017af9 193static void* client1(void*p) {
89ffcd2a
LP
194 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
195 sd_bus *bus = NULL;
196 sd_bus_error error = SD_BUS_ERROR_INIT;
197 const char *hello;
198 int r;
199
200 r = sd_bus_open_user(&bus);
201 if (r < 0) {
202 log_error("Failed to connect to user bus: %s", strerror(-r));
203 goto finish;
204 }
205
206 r = sd_bus_message_new_method_call(
207 bus,
208 "org.freedesktop.systemd.test",
209 "/",
210 "org.freedesktop.systemd.test",
211 "LowerCase",
212 &m);
213 if (r < 0) {
214 log_error("Failed to allocate method call: %s", strerror(-r));
215 goto finish;
216 }
217
218 r = sd_bus_message_append(m, "s", "HELLO");
219 if (r < 0) {
220 log_error("Failed to append string: %s", strerror(-r));
221 goto finish;
222 }
223
e3017af9 224 r = sd_bus_send_with_reply_and_block(bus, m, 0, &error, &reply);
89ffcd2a 225 if (r < 0) {
e3017af9 226 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
89ffcd2a
LP
227 goto finish;
228 }
229
230 r = sd_bus_message_read(reply, "s", &hello);
231 if (r < 0) {
232 log_error("Failed to get string: %s", strerror(-r));
233 goto finish;
234 }
235
236 assert(streq(hello, "hello"));
237
238 r = 0;
239
240finish:
241 if (bus) {
242 _cleanup_bus_message_unref_ sd_bus_message *q;
243
244 r = sd_bus_message_new_method_call(
245 bus,
246 "org.freedesktop.systemd.test",
247 "/",
248 "org.freedesktop.systemd.test",
e3017af9 249 "ExitClient1",
89ffcd2a
LP
250 &q);
251 if (r < 0) {
252 log_error("Failed to allocate method call: %s", strerror(-r));
253 goto finish;
254 }
255
256 sd_bus_send(bus, q, NULL);
257 sd_bus_flush(bus);
258 sd_bus_unref(bus);
259 }
260
261 sd_bus_error_free(&error);
e3017af9
LP
262 return INT_TO_PTR(r);
263}
264
265static int quit_callback(sd_bus *b, int ret, sd_bus_message *m, void *userdata) {
266 bool *x = userdata;
267
268 log_error("Quit callback: %s", strerror(ret));
269
270 *x = 1;
271 return 1;
272}
273
274static void* client2(void*p) {
275 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
276 sd_bus *bus = NULL;
277 sd_bus_error error = SD_BUS_ERROR_INIT;
e3017af9 278 bool quit = false;
b9bf7e2b
LP
279 const char *mid;
280 int r;
e3017af9
LP
281
282 r = sd_bus_open_user(&bus);
283 if (r < 0) {
284 log_error("Failed to connect to user bus: %s", strerror(-r));
285 goto finish;
286 }
287
b9bf7e2b
LP
288 r = sd_bus_message_new_method_call(
289 bus,
290 "org.freedesktop.systemd.test",
291 "/",
292 "org.freedesktop.DBus.Peer",
293 "GetMachineId",
294 &m);
295 if (r < 0) {
296 log_error("Failed to allocate method call: %s", strerror(-r));
297 goto finish;
298 }
299
300 r = sd_bus_send_with_reply_and_block(bus, m, 0, &error, &reply);
301 if (r < 0) {
302 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
303 goto finish;
304 }
305
306 r = sd_bus_message_read(reply, "s", &mid);
307 if (r < 0) {
308 log_error("Failed to parse machine ID: %s", strerror(-r));
309 goto finish;
310 }
311
312 log_info("Machine ID is %s.", mid);
313
314 sd_bus_message_unref(m);
315 m = NULL;
316
e3017af9
LP
317 r = sd_bus_message_new_method_call(
318 bus,
319 "org.freedesktop.systemd.test",
320 "/",
321 "org.freedesktop.systemd.test",
322 "Slow",
323 &m);
324 if (r < 0) {
325 log_error("Failed to allocate method call: %s", strerror(-r));
326 goto finish;
327 }
328
b9bf7e2b
LP
329 sd_bus_message_unref(reply);
330 reply = NULL;
331
e3017af9
LP
332 r = sd_bus_send_with_reply_and_block(bus, m, 200 * USEC_PER_MSEC, &error, &reply);
333 if (r < 0)
334 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
335 else
336 log_info("Slow call succeed.");
337
338 sd_bus_message_unref(m);
339 m = NULL;
340
341 r = sd_bus_message_new_method_call(
342 bus,
343 "org.freedesktop.systemd.test",
344 "/",
345 "org.freedesktop.systemd.test",
346 "Slow",
347 &m);
348 if (r < 0) {
349 log_error("Failed to allocate method call: %s", strerror(-r));
350 goto finish;
351 }
352
353 r = sd_bus_send_with_reply(bus, m, quit_callback, &quit, 200 * USEC_PER_MSEC, NULL);
354 if (r < 0) {
355 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
356 goto finish;
357 }
358
359 while (!quit) {
360 r = sd_bus_process(bus, NULL);
361 if (r < 0) {
362 log_error("Failed to process requests: %s", strerror(-r));
363 goto finish;
364 }
365 if (r == 0) {
366 r = sd_bus_wait(bus, (uint64_t) -1);
367 if (r < 0) {
368 log_error("Failed to wait: %s", strerror(-r));
369 goto finish;
370 }
371 }
372 }
373
374 r = 0;
375
376finish:
377 if (bus) {
378 _cleanup_bus_message_unref_ sd_bus_message *q;
379
380 r = sd_bus_message_new_method_call(
381 bus,
382 "org.freedesktop.systemd.test",
383 "/",
384 "org.freedesktop.systemd.test",
385 "ExitClient2",
386 &q);
387 if (r < 0) {
388 log_error("Failed to allocate method call: %s", strerror(-r));
389 goto finish;
390 }
391
392 sd_bus_send(bus, q, NULL);
393 sd_bus_flush(bus);
394 sd_bus_unref(bus);
395 }
396
397 sd_bus_error_free(&error);
398 return INT_TO_PTR(r);
89ffcd2a
LP
399}
400
401int main(int argc, char *argv[]) {
e3017af9 402 pthread_t c1, c2;
89ffcd2a
LP
403 sd_bus *bus;
404 void *p;
405 int q, r;
406
407 r = server_init(&bus);
408 if (r < 0)
409 return EXIT_FAILURE;
410
e3017af9
LP
411 log_info("Initialized...");
412
413 r = pthread_create(&c1, NULL, client1, bus);
414 if (r != 0)
89ffcd2a 415 return EXIT_FAILURE;
89ffcd2a 416
e3017af9
LP
417 r = pthread_create(&c2, NULL, client2, bus);
418 if (r != 0)
419 return EXIT_FAILURE;
89ffcd2a 420
e3017af9
LP
421 r = server(bus);
422
423 q = pthread_join(c1, &p);
424 if (q != 0)
425 return EXIT_FAILURE;
426 q = pthread_join(c2, &p);
89ffcd2a
LP
427 if (q != 0)
428 return EXIT_FAILURE;
429 if (r < 0)
430 return EXIT_FAILURE;
431
432 return EXIT_SUCCESS;
433}