12 #include "kdbus-api.h"
13 #include "kdbus-util.h"
14 #include "kdbus-enum.h"
15 #include "kdbus-test.h"
17 int kdbus_test_match_id_add(struct kdbus_test_env *env)
20 struct kdbus_cmd_match cmd;
24 struct kdbus_notify_id_change chg;
27 struct kdbus_conn *conn;
28 struct kdbus_msg *msg;
31 memset(&buf, 0, sizeof(buf));
33 buf.cmd.size = sizeof(buf);
34 buf.cmd.cookie = 0xdeafbeefdeaddead;
35 buf.item.size = sizeof(buf.item);
36 buf.item.type = KDBUS_ITEM_ID_ADD;
37 buf.item.chg.id = KDBUS_MATCH_ID_ANY;
40 ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd);
41 ASSERT_RETURN(ret == 0);
43 /* create 2nd connection */
44 conn = kdbus_hello(env->buspath, 0, NULL, 0);
45 ASSERT_RETURN(conn != NULL);
47 /* 1st connection should have received a notification */
48 ret = kdbus_msg_recv(env->conn, &msg, NULL);
49 ASSERT_RETURN(ret == 0);
51 ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_ID_ADD);
52 ASSERT_RETURN(msg->items[0].id_change.id == conn->id);
54 kdbus_conn_free(conn);
59 int kdbus_test_match_id_remove(struct kdbus_test_env *env)
62 struct kdbus_cmd_match cmd;
66 struct kdbus_notify_id_change chg;
69 struct kdbus_conn *conn;
70 struct kdbus_msg *msg;
74 /* create 2nd connection */
75 conn = kdbus_hello(env->buspath, 0, NULL, 0);
76 ASSERT_RETURN(conn != NULL);
79 memset(&buf, 0, sizeof(buf));
80 buf.cmd.size = sizeof(buf);
81 buf.cmd.cookie = 0xdeafbeefdeaddead;
82 buf.item.size = sizeof(buf.item);
83 buf.item.type = KDBUS_ITEM_ID_REMOVE;
86 /* register match on 2nd connection */
87 ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd);
88 ASSERT_RETURN(ret == 0);
90 /* remove 2nd connection again */
91 kdbus_conn_free(conn);
93 /* 1st connection should have received a notification */
94 ret = kdbus_msg_recv(env->conn, &msg, NULL);
95 ASSERT_RETURN(ret == 0);
97 ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_ID_REMOVE);
98 ASSERT_RETURN(msg->items[0].id_change.id == id);
103 int kdbus_test_match_replace(struct kdbus_test_env *env)
106 struct kdbus_cmd_match cmd;
110 struct kdbus_notify_id_change chg;
113 struct kdbus_conn *conn;
114 struct kdbus_msg *msg;
118 /* add a match to id_add */
119 ASSERT_RETURN(kdbus_test_match_id_add(env) == TEST_OK);
121 /* do a replace of the match from id_add to id_remove */
122 memset(&buf, 0, sizeof(buf));
124 buf.cmd.size = sizeof(buf);
125 buf.cmd.cookie = 0xdeafbeefdeaddead;
126 buf.cmd.flags = KDBUS_MATCH_REPLACE;
127 buf.item.size = sizeof(buf.item);
128 buf.item.type = KDBUS_ITEM_ID_REMOVE;
129 buf.item.chg.id = KDBUS_MATCH_ID_ANY;
131 ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd);
133 /* create 2nd connection */
134 conn = kdbus_hello(env->buspath, 0, NULL, 0);
135 ASSERT_RETURN(conn != NULL);
138 /* 1st connection should _not_ have received a notification */
139 ret = kdbus_msg_recv(env->conn, &msg, NULL);
140 ASSERT_RETURN(ret != 0);
142 /* remove 2nd connection */
143 kdbus_conn_free(conn);
145 /* 1st connection should _now_ have received a notification */
146 ret = kdbus_msg_recv(env->conn, &msg, NULL);
147 ASSERT_RETURN(ret == 0);
149 ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_ID_REMOVE);
150 ASSERT_RETURN(msg->items[0].id_change.id == id);
155 int kdbus_test_match_name_add(struct kdbus_test_env *env)
158 struct kdbus_cmd_match cmd;
162 struct kdbus_notify_name_change chg;
166 struct kdbus_msg *msg;
170 name = "foo.bla.blaz";
172 /* install the match rule */
173 memset(&buf, 0, sizeof(buf));
174 buf.item.type = KDBUS_ITEM_NAME_ADD;
175 buf.item.chg.old_id.id = KDBUS_MATCH_ID_ANY;
176 buf.item.chg.new_id.id = KDBUS_MATCH_ID_ANY;
177 strncpy(buf.name, name, sizeof(buf.name) - 1);
178 buf.item.size = sizeof(buf.item) + strlen(buf.name) + 1;
179 buf.cmd.size = sizeof(buf.cmd) + buf.item.size;
181 ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd);
182 ASSERT_RETURN(ret == 0);
184 /* acquire the name */
185 ret = kdbus_name_acquire(env->conn, name, NULL);
186 ASSERT_RETURN(ret == 0);
188 /* we should have received a notification */
189 ret = kdbus_msg_recv(env->conn, &msg, NULL);
190 ASSERT_RETURN(ret == 0);
192 ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_NAME_ADD);
193 ASSERT_RETURN(msg->items[0].name_change.old_id.id == 0);
194 ASSERT_RETURN(msg->items[0].name_change.new_id.id == env->conn->id);
195 ASSERT_RETURN(strcmp(msg->items[0].name_change.name, name) == 0);
200 int kdbus_test_match_name_remove(struct kdbus_test_env *env)
203 struct kdbus_cmd_match cmd;
207 struct kdbus_notify_name_change chg;
211 struct kdbus_msg *msg;
215 name = "foo.bla.blaz";
217 /* acquire the name */
218 ret = kdbus_name_acquire(env->conn, name, NULL);
219 ASSERT_RETURN(ret == 0);
221 /* install the match rule */
222 memset(&buf, 0, sizeof(buf));
223 buf.item.type = KDBUS_ITEM_NAME_REMOVE;
224 buf.item.chg.old_id.id = KDBUS_MATCH_ID_ANY;
225 buf.item.chg.new_id.id = KDBUS_MATCH_ID_ANY;
226 strncpy(buf.name, name, sizeof(buf.name) - 1);
227 buf.item.size = sizeof(buf.item) + strlen(buf.name) + 1;
228 buf.cmd.size = sizeof(buf.cmd) + buf.item.size;
230 ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd);
231 ASSERT_RETURN(ret == 0);
233 /* release the name again */
234 kdbus_name_release(env->conn, name);
235 ASSERT_RETURN(ret == 0);
237 /* we should have received a notification */
238 ret = kdbus_msg_recv(env->conn, &msg, NULL);
239 ASSERT_RETURN(ret == 0);
241 ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_NAME_REMOVE);
242 ASSERT_RETURN(msg->items[0].name_change.old_id.id == env->conn->id);
243 ASSERT_RETURN(msg->items[0].name_change.new_id.id == 0);
244 ASSERT_RETURN(strcmp(msg->items[0].name_change.name, name) == 0);
249 int kdbus_test_match_name_change(struct kdbus_test_env *env)
252 struct kdbus_cmd_match cmd;
256 struct kdbus_notify_name_change chg;
260 struct kdbus_conn *conn;
261 struct kdbus_msg *msg;
263 char *name = "foo.bla.baz";
266 /* acquire the name */
267 ret = kdbus_name_acquire(env->conn, name, NULL);
268 ASSERT_RETURN(ret == 0);
270 /* install the match rule */
271 memset(&buf, 0, sizeof(buf));
272 buf.item.type = KDBUS_ITEM_NAME_CHANGE;
273 buf.item.chg.old_id.id = KDBUS_MATCH_ID_ANY;
274 buf.item.chg.new_id.id = KDBUS_MATCH_ID_ANY;
275 strncpy(buf.name, name, sizeof(buf.name) - 1);
276 buf.item.size = sizeof(buf.item) + strlen(buf.name) + 1;
277 buf.cmd.size = sizeof(buf.cmd) + buf.item.size;
279 ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd);
280 ASSERT_RETURN(ret == 0);
282 /* create a 2nd connection */
283 conn = kdbus_hello(env->buspath, 0, NULL, 0);
284 ASSERT_RETURN(conn != NULL);
286 /* allow the new connection to own the same name */
287 /* queue the 2nd connection as waiting owner */
288 flags = KDBUS_NAME_QUEUE;
289 ret = kdbus_name_acquire(conn, name, &flags);
290 ASSERT_RETURN(ret == 0);
291 ASSERT_RETURN(flags & KDBUS_NAME_IN_QUEUE);
293 /* release name from 1st connection */
294 ret = kdbus_name_release(env->conn, name);
295 ASSERT_RETURN(ret == 0);
297 /* we should have received a notification */
298 ret = kdbus_msg_recv(env->conn, &msg, NULL);
299 ASSERT_RETURN(ret == 0);
301 ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_NAME_CHANGE);
302 ASSERT_RETURN(msg->items[0].name_change.old_id.id == env->conn->id);
303 ASSERT_RETURN(msg->items[0].name_change.new_id.id == conn->id);
304 ASSERT_RETURN(strcmp(msg->items[0].name_change.name, name) == 0);
306 kdbus_conn_free(conn);
311 static int send_bloom_filter(const struct kdbus_conn *conn,
313 const uint8_t *filter,
315 uint64_t filter_generation)
317 struct kdbus_cmd_send cmd = {};
318 struct kdbus_msg *msg;
319 struct kdbus_item *item;
323 size = sizeof(struct kdbus_msg);
324 size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + filter_size;
328 memset(msg, 0, size);
330 msg->src_id = conn->id;
331 msg->dst_id = KDBUS_DST_ID_BROADCAST;
332 msg->flags = KDBUS_MSG_SIGNAL;
333 msg->payload_type = KDBUS_PAYLOAD_DBUS;
334 msg->cookie = cookie;
337 item->type = KDBUS_ITEM_BLOOM_FILTER;
338 item->size = KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) +
341 item->bloom_filter.generation = filter_generation;
342 memcpy(item->bloom_filter.data, filter, filter_size);
344 cmd.size = sizeof(cmd);
345 cmd.msg_address = (uintptr_t)msg;
347 ret = kdbus_cmd_send(conn->fd, &cmd);
349 kdbus_printf("error sending message: %d (%m)\n", ret);
356 int kdbus_test_match_bloom(struct kdbus_test_env *env)
359 struct kdbus_cmd_match cmd;
363 uint8_t data_gen0[64];
364 uint8_t data_gen1[64];
367 struct kdbus_conn *conn;
368 struct kdbus_msg *msg;
369 uint64_t cookie = 0xf000f00f;
373 /* install the match rule */
374 memset(&buf, 0, sizeof(buf));
375 buf.cmd.size = sizeof(buf);
377 buf.item.size = sizeof(buf.item);
378 buf.item.type = KDBUS_ITEM_BLOOM_MASK;
379 buf.item.data_gen0[0] = 0x55;
380 buf.item.data_gen0[63] = 0x80;
382 buf.item.data_gen1[1] = 0xaa;
383 buf.item.data_gen1[9] = 0x02;
385 ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd);
386 ASSERT_RETURN(ret == 0);
388 /* create a 2nd connection */
389 conn = kdbus_hello(env->buspath, 0, NULL, 0);
390 ASSERT_RETURN(conn != NULL);
392 /* a message with a 0'ed out filter must not reach the other peer */
393 memset(filter, 0, sizeof(filter));
394 ret = send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 0);
395 ASSERT_RETURN(ret == 0);
397 ret = kdbus_msg_recv(env->conn, &msg, NULL);
398 ASSERT_RETURN(ret == -EAGAIN);
400 /* now set the filter to the connection's mask and expect success */
403 ret = send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 0);
404 ASSERT_RETURN(ret == 0);
406 ret = kdbus_msg_recv(env->conn, &msg, NULL);
407 ASSERT_RETURN(ret == 0);
408 ASSERT_RETURN(msg->cookie == cookie);
410 /* broaden the filter and try again. this should also succeed. */
414 ret = send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 0);
415 ASSERT_RETURN(ret == 0);
417 ret = kdbus_msg_recv(env->conn, &msg, NULL);
418 ASSERT_RETURN(ret == 0);
419 ASSERT_RETURN(msg->cookie == cookie);
421 /* the same filter must not match against bloom generation 1 */
422 ret = send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 1);
423 ASSERT_RETURN(ret == 0);
425 ret = kdbus_msg_recv(env->conn, &msg, NULL);
426 ASSERT_RETURN(ret == -EAGAIN);
428 /* set a different filter and try again */
431 ret = send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 1);
432 ASSERT_RETURN(ret == 0);
434 ret = kdbus_msg_recv(env->conn, &msg, NULL);
435 ASSERT_RETURN(ret == 0);
436 ASSERT_RETURN(msg->cookie == cookie);
438 kdbus_conn_free(conn);