]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/test-bus-chat.c
bus: enforce limits on all client influenced data objects
[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;
36 int r;
37
38 assert(_bus);
39
40 r = sd_bus_open_user(&bus);
41 if (r < 0) {
42 log_error("Failed to connect to user bus: %s", strerror(-r));
43 goto fail;
44 }
45
46 r = sd_bus_request_name(bus, "org.freedesktop.systemd.test", 0);
47 if (r < 0) {
48 log_error("Failed to acquire name: %s", strerror(-r));
49 goto fail;
50 }
51
52 *_bus = bus;
53 return 0;
54
55fail:
56 if (bus)
57 sd_bus_unref(bus);
58
59 return r;
60}
61
e3017af9 62static int server(sd_bus *bus) {
89ffcd2a 63 int r;
e3017af9 64 bool client1_gone = false, client2_gone = false;
89ffcd2a 65
e3017af9 66 while (!client1_gone || !client2_gone) {
89ffcd2a
LP
67 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
68
69 r = sd_bus_process(bus, &m);
70 if (r < 0) {
71 log_error("Failed to process requests: %s", strerror(-r));
72 goto fail;
73 }
e3017af9 74
89ffcd2a
LP
75 if (r == 0) {
76 r = sd_bus_wait(bus, (uint64_t) -1);
77 if (r < 0) {
78 log_error("Failed to wait: %s", strerror(-r));
79 goto fail;
80 }
81
82 continue;
83 }
84
e3017af9
LP
85 if (!m)
86 continue;
87
89ffcd2a
LP
88 log_info("Got message! %s", strna(sd_bus_message_get_member(m)));
89 /* bus_message_dump(m); */
90 /* sd_bus_message_rewind(m, true); */
91
92 if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "LowerCase")) {
93 const char *hello;
94 _cleanup_free_ char *lowercase = NULL;
95
96 r = sd_bus_message_read(m, "s", &hello);
97 if (r < 0) {
98 log_error("Failed to get parameter: %s", strerror(-r));
99 goto fail;
100 }
101
102 r = sd_bus_message_new_method_return(bus, m, &reply);
103 if (r < 0) {
104 log_error("Failed to allocate return: %s", strerror(-r));
105 goto fail;
106 }
107
108 lowercase = strdup(hello);
109 if (!lowercase) {
110 r = log_oom();
111 goto fail;
112 }
113
114 ascii_strlower(lowercase);
115
116 r = sd_bus_message_append(reply, "s", lowercase);
117 if (r < 0) {
118 log_error("Failed to append message: %s", strerror(-r));
119 goto fail;
120 }
e3017af9
LP
121 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient1")) {
122
123 r = sd_bus_message_new_method_return(bus, m, &reply);
124 if (r < 0) {
125 log_error("Failed to allocate return: %s", strerror(-r));
126 goto fail;
127 }
128
129 client1_gone = true;
130 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient2")) {
131
132 r = sd_bus_message_new_method_return(bus, m, &reply);
133 if (r < 0) {
134 log_error("Failed to allocate return: %s", strerror(-r));
135 goto fail;
136 }
137
138 client2_gone = true;
139 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Slow")) {
140
141 r = sd_bus_message_new_method_return(bus, m, &reply);
142 if (r < 0) {
143 log_error("Failed to allocate return: %s", strerror(-r));
144 goto fail;
145 }
146
147 sleep(1);
148 } else if (sd_bus_message_is_method_call(m, NULL, NULL)) {
89ffcd2a
LP
149 const sd_bus_error e = SD_BUS_ERROR_INIT_CONST("org.freedesktop.DBus.Error.UnknownMethod", "Unknown method.");
150
151 r = sd_bus_message_new_method_error(bus, m, &e, &reply);
152 if (r < 0) {
153 log_error("Failed to allocate return: %s", strerror(-r));
154 goto fail;
155 }
156 }
157
158 if (reply) {
159 r = sd_bus_send(bus, reply, NULL);
160 if (r < 0) {
161 log_error("Failed to send reply: %s", strerror(-r));
162 goto fail;
163 }
e3017af9
LP
164
165 /* log_info("Sent"); */
166 /* bus_message_dump(reply); */
167 /* sd_bus_message_rewind(reply, true); */
89ffcd2a
LP
168 }
169 }
170
171 r = 0;
172
173fail:
e3017af9
LP
174 if (bus) {
175 sd_bus_flush(bus);
89ffcd2a 176 sd_bus_unref(bus);
e3017af9 177 }
89ffcd2a 178
e3017af9 179 return r;
89ffcd2a
LP
180}
181
e3017af9 182static void* client1(void*p) {
89ffcd2a
LP
183 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
184 sd_bus *bus = NULL;
185 sd_bus_error error = SD_BUS_ERROR_INIT;
186 const char *hello;
187 int r;
188
189 r = sd_bus_open_user(&bus);
190 if (r < 0) {
191 log_error("Failed to connect to user bus: %s", strerror(-r));
192 goto finish;
193 }
194
195 r = sd_bus_message_new_method_call(
196 bus,
197 "org.freedesktop.systemd.test",
198 "/",
199 "org.freedesktop.systemd.test",
200 "LowerCase",
201 &m);
202 if (r < 0) {
203 log_error("Failed to allocate method call: %s", strerror(-r));
204 goto finish;
205 }
206
207 r = sd_bus_message_append(m, "s", "HELLO");
208 if (r < 0) {
209 log_error("Failed to append string: %s", strerror(-r));
210 goto finish;
211 }
212
e3017af9 213 r = sd_bus_send_with_reply_and_block(bus, m, 0, &error, &reply);
89ffcd2a 214 if (r < 0) {
e3017af9 215 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
89ffcd2a
LP
216 goto finish;
217 }
218
219 r = sd_bus_message_read(reply, "s", &hello);
220 if (r < 0) {
221 log_error("Failed to get string: %s", strerror(-r));
222 goto finish;
223 }
224
225 assert(streq(hello, "hello"));
226
227 r = 0;
228
229finish:
230 if (bus) {
231 _cleanup_bus_message_unref_ sd_bus_message *q;
232
233 r = sd_bus_message_new_method_call(
234 bus,
235 "org.freedesktop.systemd.test",
236 "/",
237 "org.freedesktop.systemd.test",
e3017af9 238 "ExitClient1",
89ffcd2a
LP
239 &q);
240 if (r < 0) {
241 log_error("Failed to allocate method call: %s", strerror(-r));
242 goto finish;
243 }
244
245 sd_bus_send(bus, q, NULL);
246 sd_bus_flush(bus);
247 sd_bus_unref(bus);
248 }
249
250 sd_bus_error_free(&error);
e3017af9
LP
251 return INT_TO_PTR(r);
252}
253
254static int quit_callback(sd_bus *b, int ret, sd_bus_message *m, void *userdata) {
255 bool *x = userdata;
256
257 log_error("Quit callback: %s", strerror(ret));
258
259 *x = 1;
260 return 1;
261}
262
263static void* client2(void*p) {
264 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
265 sd_bus *bus = NULL;
266 sd_bus_error error = SD_BUS_ERROR_INIT;
267 int r;
268 bool quit = false;
269
270 r = sd_bus_open_user(&bus);
271 if (r < 0) {
272 log_error("Failed to connect to user bus: %s", strerror(-r));
273 goto finish;
274 }
275
276 r = sd_bus_message_new_method_call(
277 bus,
278 "org.freedesktop.systemd.test",
279 "/",
280 "org.freedesktop.systemd.test",
281 "Slow",
282 &m);
283 if (r < 0) {
284 log_error("Failed to allocate method call: %s", strerror(-r));
285 goto finish;
286 }
287
288 r = sd_bus_send_with_reply_and_block(bus, m, 200 * USEC_PER_MSEC, &error, &reply);
289 if (r < 0)
290 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
291 else
292 log_info("Slow call succeed.");
293
294 sd_bus_message_unref(m);
295 m = NULL;
296
297 r = sd_bus_message_new_method_call(
298 bus,
299 "org.freedesktop.systemd.test",
300 "/",
301 "org.freedesktop.systemd.test",
302 "Slow",
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(bus, m, quit_callback, &quit, 200 * USEC_PER_MSEC, NULL);
310 if (r < 0) {
311 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
312 goto finish;
313 }
314
315 while (!quit) {
316 r = sd_bus_process(bus, NULL);
317 if (r < 0) {
318 log_error("Failed to process requests: %s", strerror(-r));
319 goto finish;
320 }
321 if (r == 0) {
322 r = sd_bus_wait(bus, (uint64_t) -1);
323 if (r < 0) {
324 log_error("Failed to wait: %s", strerror(-r));
325 goto finish;
326 }
327 }
328 }
329
330 r = 0;
331
332finish:
333 if (bus) {
334 _cleanup_bus_message_unref_ sd_bus_message *q;
335
336 r = sd_bus_message_new_method_call(
337 bus,
338 "org.freedesktop.systemd.test",
339 "/",
340 "org.freedesktop.systemd.test",
341 "ExitClient2",
342 &q);
343 if (r < 0) {
344 log_error("Failed to allocate method call: %s", strerror(-r));
345 goto finish;
346 }
347
348 sd_bus_send(bus, q, NULL);
349 sd_bus_flush(bus);
350 sd_bus_unref(bus);
351 }
352
353 sd_bus_error_free(&error);
354 return INT_TO_PTR(r);
89ffcd2a
LP
355}
356
357int main(int argc, char *argv[]) {
e3017af9 358 pthread_t c1, c2;
89ffcd2a
LP
359 sd_bus *bus;
360 void *p;
361 int q, r;
362
363 r = server_init(&bus);
364 if (r < 0)
365 return EXIT_FAILURE;
366
e3017af9
LP
367 log_info("Initialized...");
368
369 r = pthread_create(&c1, NULL, client1, bus);
370 if (r != 0)
89ffcd2a 371 return EXIT_FAILURE;
89ffcd2a 372
e3017af9
LP
373 r = pthread_create(&c2, NULL, client2, bus);
374 if (r != 0)
375 return EXIT_FAILURE;
89ffcd2a 376
e3017af9
LP
377 r = server(bus);
378
379 q = pthread_join(c1, &p);
380 if (q != 0)
381 return EXIT_FAILURE;
382 q = pthread_join(c2, &p);
89ffcd2a
LP
383 if (q != 0)
384 return EXIT_FAILURE;
385 if (r < 0)
386 return EXIT_FAILURE;
387
388 return EXIT_SUCCESS;
389}