]> git.ipfire.org Git - thirdparty/systemd.git/blame_incremental - src/libsystemd-bus/test-bus-chat.c
mount: mount all cgroup controllers in containers, too
[thirdparty/systemd.git] / src / libsystemd-bus / test-bus-chat.c
... / ...
CommitLineData
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>
25#include <unistd.h>
26
27#include "log.h"
28#include "util.h"
29
30#include "sd-bus.h"
31#include "bus-message.h"
32#include "bus-error.h"
33
34static int server_init(sd_bus **_bus) {
35 sd_bus *bus = NULL;
36 sd_id128_t id;
37 int r;
38 const char *unique;
39
40 assert(_bus);
41
42 r = sd_bus_open_user(&bus);
43 if (r < 0) {
44 log_error("Failed to connect to user bus: %s", strerror(-r));
45 goto fail;
46 }
47
48 r = sd_bus_get_peer(bus, &id);
49 if (r < 0) {
50 log_error("Failed to get peer ID: %s", strerror(-r));
51 goto fail;
52 }
53
54 r = sd_bus_get_unique_name(bus, &unique);
55 if (r < 0) {
56 log_error("Failed to get unique name: %s", strerror(-r));
57 goto fail;
58 }
59
60 log_info("Peer ID is " SD_ID128_FORMAT_STR ".", SD_ID128_FORMAT_VAL(id));
61 log_info("Unique ID: %s", unique);
62 log_info("Can send file handles: %i", sd_bus_can_send(bus, 'h'));
63
64 r = sd_bus_request_name(bus, "org.freedesktop.systemd.test", 0);
65 if (r < 0) {
66 log_error("Failed to acquire name: %s", strerror(-r));
67 goto fail;
68 }
69
70 *_bus = bus;
71 return 0;
72
73fail:
74 if (bus)
75 sd_bus_unref(bus);
76
77 return r;
78}
79
80static int server(sd_bus *bus) {
81 int r;
82 bool client1_gone = false, client2_gone = false;
83
84 while (!client1_gone || !client2_gone) {
85 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
86 pid_t pid = 0;
87
88 r = sd_bus_process(bus, &m);
89 if (r < 0) {
90 log_error("Failed to process requests: %s", strerror(-r));
91 goto fail;
92 }
93
94 if (r == 0) {
95 r = sd_bus_wait(bus, (uint64_t) -1);
96 if (r < 0) {
97 log_error("Failed to wait: %s", strerror(-r));
98 goto fail;
99 }
100
101 continue;
102 }
103
104 if (!m)
105 continue;
106
107 sd_bus_message_get_pid(m, &pid);
108 log_info("Got message! member=%s pid=%lu label=%s", strna(sd_bus_message_get_member(m)), (unsigned long) pid, strna(sd_bus_message_get_label(m)));
109 /* bus_message_dump(m); */
110 /* sd_bus_message_rewind(m, true); */
111
112 if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "LowerCase")) {
113 const char *hello;
114 _cleanup_free_ char *lowercase = NULL;
115
116 r = sd_bus_message_read(m, "s", &hello);
117 if (r < 0) {
118 log_error("Failed to get parameter: %s", strerror(-r));
119 goto fail;
120 }
121
122 r = sd_bus_message_new_method_return(bus, m, &reply);
123 if (r < 0) {
124 log_error("Failed to allocate return: %s", strerror(-r));
125 goto fail;
126 }
127
128 lowercase = strdup(hello);
129 if (!lowercase) {
130 r = log_oom();
131 goto fail;
132 }
133
134 ascii_strlower(lowercase);
135
136 r = sd_bus_message_append(reply, "s", lowercase);
137 if (r < 0) {
138 log_error("Failed to append message: %s", strerror(-r));
139 goto fail;
140 }
141 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient1")) {
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 client1_gone = true;
150 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient2")) {
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 client2_gone = true;
159 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Slow")) {
160
161 r = sd_bus_message_new_method_return(bus, m, &reply);
162 if (r < 0) {
163 log_error("Failed to allocate return: %s", strerror(-r));
164 goto fail;
165 }
166
167 sleep(1);
168 } else if (sd_bus_message_is_method_call(m, NULL, NULL)) {
169 const sd_bus_error e = SD_BUS_ERROR_INIT_CONST("org.freedesktop.DBus.Error.UnknownMethod", "Unknown method.");
170
171 r = sd_bus_message_new_method_error(bus, m, &e, &reply);
172 if (r < 0) {
173 log_error("Failed to allocate return: %s", strerror(-r));
174 goto fail;
175 }
176 }
177
178 if (reply) {
179 r = sd_bus_send(bus, reply, NULL);
180 if (r < 0) {
181 log_error("Failed to send reply: %s", strerror(-r));
182 goto fail;
183 }
184
185 /* log_info("Sent"); */
186 /* bus_message_dump(reply); */
187 /* sd_bus_message_rewind(reply, true); */
188 }
189 }
190
191 r = 0;
192
193fail:
194 if (bus) {
195 sd_bus_flush(bus);
196 sd_bus_unref(bus);
197 }
198
199 return r;
200}
201
202static void* client1(void*p) {
203 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
204 sd_bus *bus = NULL;
205 sd_bus_error error = SD_BUS_ERROR_INIT;
206 const char *hello;
207 int r;
208
209 r = sd_bus_open_user(&bus);
210 if (r < 0) {
211 log_error("Failed to connect to user bus: %s", strerror(-r));
212 goto finish;
213 }
214
215 r = sd_bus_message_new_method_call(
216 bus,
217 "org.freedesktop.systemd.test",
218 "/",
219 "org.freedesktop.systemd.test",
220 "LowerCase",
221 &m);
222 if (r < 0) {
223 log_error("Failed to allocate method call: %s", strerror(-r));
224 goto finish;
225 }
226
227 r = sd_bus_message_append(m, "s", "HELLO");
228 if (r < 0) {
229 log_error("Failed to append string: %s", strerror(-r));
230 goto finish;
231 }
232
233 r = sd_bus_send_with_reply_and_block(bus, m, 0, &error, &reply);
234 if (r < 0) {
235 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
236 goto finish;
237 }
238
239 r = sd_bus_message_read(reply, "s", &hello);
240 if (r < 0) {
241 log_error("Failed to get string: %s", strerror(-r));
242 goto finish;
243 }
244
245 assert(streq(hello, "hello"));
246
247 r = 0;
248
249finish:
250 if (bus) {
251 _cleanup_bus_message_unref_ sd_bus_message *q;
252
253 r = sd_bus_message_new_method_call(
254 bus,
255 "org.freedesktop.systemd.test",
256 "/",
257 "org.freedesktop.systemd.test",
258 "ExitClient1",
259 &q);
260 if (r < 0) {
261 log_error("Failed to allocate method call: %s", strerror(-r));
262 goto finish;
263 }
264
265 sd_bus_send(bus, q, NULL);
266 sd_bus_flush(bus);
267 sd_bus_unref(bus);
268 }
269
270 sd_bus_error_free(&error);
271 return INT_TO_PTR(r);
272}
273
274static int quit_callback(sd_bus *b, int ret, sd_bus_message *m, void *userdata) {
275 bool *x = userdata;
276
277 log_error("Quit callback: %s", strerror(ret));
278
279 *x = 1;
280 return 1;
281}
282
283static void* client2(void*p) {
284 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
285 sd_bus *bus = NULL;
286 sd_bus_error error = SD_BUS_ERROR_INIT;
287 bool quit = false;
288 const char *mid;
289 int r;
290
291 r = sd_bus_open_user(&bus);
292 if (r < 0) {
293 log_error("Failed to connect to user bus: %s", strerror(-r));
294 goto finish;
295 }
296
297 r = sd_bus_message_new_method_call(
298 bus,
299 "org.freedesktop.systemd.test",
300 "/",
301 "org.freedesktop.DBus.Peer",
302 "GetMachineId",
303 &m);
304 if (r < 0) {
305 log_error("Failed to allocate method call: %s", strerror(-r));
306 goto finish;
307 }
308
309 r = sd_bus_send_with_reply_and_block(bus, m, 0, &error, &reply);
310 if (r < 0) {
311 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
312 goto finish;
313 }
314
315 r = sd_bus_message_read(reply, "s", &mid);
316 if (r < 0) {
317 log_error("Failed to parse machine ID: %s", strerror(-r));
318 goto finish;
319 }
320
321 log_info("Machine ID is %s.", mid);
322
323 sd_bus_message_unref(m);
324 m = NULL;
325
326 r = sd_bus_message_new_method_call(
327 bus,
328 "org.freedesktop.systemd.test",
329 "/",
330 "org.freedesktop.systemd.test",
331 "Slow",
332 &m);
333 if (r < 0) {
334 log_error("Failed to allocate method call: %s", strerror(-r));
335 goto finish;
336 }
337
338 sd_bus_message_unref(reply);
339 reply = NULL;
340
341 r = sd_bus_send_with_reply_and_block(bus, m, 200 * USEC_PER_MSEC, &error, &reply);
342 if (r < 0)
343 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
344 else
345 log_info("Slow call succeed.");
346
347 sd_bus_message_unref(m);
348 m = NULL;
349
350 r = sd_bus_message_new_method_call(
351 bus,
352 "org.freedesktop.systemd.test",
353 "/",
354 "org.freedesktop.systemd.test",
355 "Slow",
356 &m);
357 if (r < 0) {
358 log_error("Failed to allocate method call: %s", strerror(-r));
359 goto finish;
360 }
361
362 r = sd_bus_send_with_reply(bus, m, quit_callback, &quit, 200 * USEC_PER_MSEC, NULL);
363 if (r < 0) {
364 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
365 goto finish;
366 }
367
368 while (!quit) {
369 r = sd_bus_process(bus, NULL);
370 if (r < 0) {
371 log_error("Failed to process requests: %s", strerror(-r));
372 goto finish;
373 }
374 if (r == 0) {
375 r = sd_bus_wait(bus, (uint64_t) -1);
376 if (r < 0) {
377 log_error("Failed to wait: %s", strerror(-r));
378 goto finish;
379 }
380 }
381 }
382
383 r = 0;
384
385finish:
386 if (bus) {
387 _cleanup_bus_message_unref_ sd_bus_message *q;
388
389 r = sd_bus_message_new_method_call(
390 bus,
391 "org.freedesktop.systemd.test",
392 "/",
393 "org.freedesktop.systemd.test",
394 "ExitClient2",
395 &q);
396 if (r < 0) {
397 log_error("Failed to allocate method call: %s", strerror(-r));
398 goto finish;
399 }
400
401 sd_bus_send(bus, q, NULL);
402 sd_bus_flush(bus);
403 sd_bus_unref(bus);
404 }
405
406 sd_bus_error_free(&error);
407 return INT_TO_PTR(r);
408}
409
410int main(int argc, char *argv[]) {
411 pthread_t c1, c2;
412 sd_bus *bus;
413 void *p;
414 int q, r;
415
416 r = server_init(&bus);
417 if (r < 0)
418 return EXIT_FAILURE;
419
420 log_info("Initialized...");
421
422 r = pthread_create(&c1, NULL, client1, bus);
423 if (r != 0)
424 return EXIT_FAILURE;
425
426 r = pthread_create(&c2, NULL, client2, bus);
427 if (r != 0)
428 return EXIT_FAILURE;
429
430 r = server(bus);
431
432 q = pthread_join(c1, &p);
433 if (q != 0)
434 return EXIT_FAILURE;
435 q = pthread_join(c2, &p);
436 if (q != 0)
437 return EXIT_FAILURE;
438 if (r < 0)
439 return EXIT_FAILURE;
440
441 return EXIT_SUCCESS;
442}