1 /* GLib testing framework examples and tests
2 *
3 * Copyright (C) 2008-2010 Red Hat, Inc.
4 *
5 * SPDX-License-Identifier: LGPL-2.1-or-later
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General
18 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 *
20 * Author: David Zeuthen <davidz@redhat.com>
21 */
22
23 #include "config.h"
24
25 #include <gio/gio.h>
26 #include <string.h>
27
28 /* for open(2) */
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <string.h>
33
34 /* for g_unlink() */
35 #include <glib/gstdio.h>
36
37 #include <gio/gnetworking.h>
38 #include <gio/gunixsocketaddress.h>
39 #include <gio/gunixfdlist.h>
40 #include <gio/gcredentialsprivate.h>
41
42 #ifdef G_OS_UNIX
43 #include <gio/gunixconnection.h>
44 #include <errno.h>
45 #endif
46
47 #ifdef G_OS_WIN32
48 #include <gio/giowin32-afunix.h>
49 #endif
50
51 #include "gdbus-tests.h"
52
53 #include "gdbus-object-manager-example/objectmanager-gen.h"
54
55 #ifdef G_OS_UNIX
56 static gboolean is_unix = TRUE;
57 #else
58 static gboolean is_unix = FALSE;
59 #endif
60
61 static gchar *tmpdir = NULL;
62 static gchar *tmp_address = NULL;
63 static gchar *test_guid = NULL;
64 static GMutex service_loop_lock;
65 static GCond service_loop_cond;
66 static GMainLoop *service_loop = NULL;
67 static GDBusServer *server = NULL;
68 static GMainLoop *loop = NULL;
69
70 /* ---------------------------------------------------------------------------------------------------- */
71 /* Test that peer-to-peer connections work */
72 /* ---------------------------------------------------------------------------------------------------- */
73
74
75 typedef struct
76 {
77 gboolean accept_connection;
78 gint num_connection_attempts;
79 GPtrArray *current_connections;
80 guint num_method_calls;
81 gboolean signal_received;
82 } PeerData;
83
84 /* This needs to be enough to usually take more than one write(),
85 * to reproduce
86 * <https://gitlab.gnome.org/GNOME/glib/-/issues/2074>.
87 * 1 MiB ought to be enough. */
88 #define BIG_MESSAGE_ARRAY_SIZE (1024 * 1024)
89
90 static const gchar *test_interface_introspection_xml =
91 "<node>"
92 " <interface name='org.gtk.GDBus.PeerTestInterface'>"
93 " <method name='HelloPeer'>"
94 " <arg type='s' name='greeting' direction='in'/>"
95 " <arg type='s' name='response' direction='out'/>"
96 " </method>"
97 " <method name='EmitSignal'/>"
98 " <method name='EmitSignalWithNameSet'/>"
99 " <method name='OpenFile'>"
100 " <arg type='s' name='path' direction='in'/>"
101 " </method>"
102 " <method name='OpenFileWithBigMessage'>"
103 " <arg type='s' name='path' direction='in'/>"
104 " <arg type='h' name='handle' direction='out'/>"
105 " <arg type='ay' name='junk' direction='out'/>"
106 " </method>"
107 " <signal name='PeerSignal'>"
108 " <arg type='s' name='a_string'/>"
109 " </signal>"
110 " <property type='s' name='PeerProperty' access='read'/>"
111 " </interface>"
112 "</node>";
113 static GDBusInterfaceInfo *test_interface_introspection_data = NULL;
114
115 static void
116 test_interface_method_call (GDBusConnection *connection,
117 const gchar *sender,
118 const gchar *object_path,
119 const gchar *interface_name,
120 const gchar *method_name,
121 GVariant *parameters,
122 GDBusMethodInvocation *invocation,
123 gpointer user_data)
124 {
125 PeerData *data = user_data;
126 const GDBusMethodInfo *info;
127
128 data->num_method_calls++;
129
130 g_assert_cmpstr (object_path, ==, "/org/gtk/GDBus/PeerTestObject");
131 g_assert_cmpstr (interface_name, ==, "org.gtk.GDBus.PeerTestInterface");
132
133 info = g_dbus_method_invocation_get_method_info (invocation);
134 g_assert_cmpstr (info->name, ==, method_name);
135
136 if (g_strcmp0 (method_name, "HelloPeer") == 0)
137 {
138 const gchar *greeting;
139 gchar *response;
140
141 g_variant_get (parameters, "(&s)", &greeting);
142
143 response = g_strdup_printf ("You greeted me with '%s'.",
144 greeting);
145 g_dbus_method_invocation_return_value (invocation,
146 g_variant_new ("(s)", response));
147 g_free (response);
148 }
149 else if (g_strcmp0 (method_name, "EmitSignal") == 0)
150 {
151 GError *error;
152
153 error = NULL;
154 g_dbus_connection_emit_signal (connection,
155 NULL,
156 "/org/gtk/GDBus/PeerTestObject",
157 "org.gtk.GDBus.PeerTestInterface",
158 "PeerSignal",
159 NULL,
160 &error);
161 g_assert_no_error (error);
162 g_dbus_method_invocation_return_value (invocation, NULL);
163 }
164 else if (g_strcmp0 (method_name, "EmitSignalWithNameSet") == 0)
165 {
166 GError *error;
167 gboolean ret;
168 GDBusMessage *message;
169
170 message = g_dbus_message_new_signal ("/org/gtk/GDBus/PeerTestObject",
171 "org.gtk.GDBus.PeerTestInterface",
172 "PeerSignalWithNameSet");
173 g_dbus_message_set_sender (message, ":1.42");
174
175 error = NULL;
176 ret = g_dbus_connection_send_message (connection, message, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &error);
177 g_assert_no_error (error);
178 g_assert (ret);
179 g_object_unref (message);
180
181 g_dbus_method_invocation_return_value (invocation, NULL);
182 }
183 else if (g_strcmp0 (method_name, "OpenFile") == 0 ||
184 g_strcmp0 (method_name, "OpenFileWithBigMessage") == 0)
185 {
186 #ifdef G_OS_UNIX
187 const gchar *path;
188 GDBusMessage *reply;
189 GError *error;
190 gint fd;
191 GUnixFDList *fd_list;
192
193 g_variant_get (parameters, "(&s)", &path);
194
195 fd_list = g_unix_fd_list_new ();
196
197 error = NULL;
198
199 fd = g_open (path, O_RDONLY, 0);
200 g_assert (fd != -1);
201 g_unix_fd_list_append (fd_list, fd, &error);
202 g_assert_no_error (error);
203 close (fd);
204
205 reply = g_dbus_message_new_method_reply (g_dbus_method_invocation_get_message (invocation));
206 g_dbus_message_set_unix_fd_list (reply, fd_list);
207 g_object_unref (fd_list);
208 g_object_unref (invocation);
209
210 if (g_strcmp0 (method_name, "OpenFileWithBigMessage") == 0)
211 {
212 char *junk;
213
214 junk = g_new0 (char, BIG_MESSAGE_ARRAY_SIZE);
215 g_dbus_message_set_body (reply,
216 g_variant_new ("(h@ay)",
217 0,
218 g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
219 junk,
220 BIG_MESSAGE_ARRAY_SIZE,
221 1)));
222 g_free (junk);
223 }
224
225 error = NULL;
226 g_dbus_connection_send_message (connection,
227 reply,
228 G_DBUS_SEND_MESSAGE_FLAGS_NONE,
229 NULL, /* out_serial */
230 &error);
231 g_assert_no_error (error);
232 g_object_unref (reply);
233 #else
234 g_dbus_method_invocation_return_dbus_error (invocation,
235 "org.gtk.GDBus.NotOnUnix",
236 "Your OS does not support file descriptor passing");
237 #endif
238 }
239 else
240 {
241 g_assert_not_reached ();
242 }
243 }
244
245 static GVariant *
246 test_interface_get_property (GDBusConnection *connection,
247 const gchar *sender,
248 const gchar *object_path,
249 const gchar *interface_name,
250 const gchar *property_name,
251 GError **error,
252 gpointer user_data)
253 {
254 g_assert_cmpstr (object_path, ==, "/org/gtk/GDBus/PeerTestObject");
255 g_assert_cmpstr (interface_name, ==, "org.gtk.GDBus.PeerTestInterface");
256 g_assert_cmpstr (property_name, ==, "PeerProperty");
257
258 return g_variant_new_string ("ThePropertyValue");
259 }
260
261
262 static const GDBusInterfaceVTable test_interface_vtable =
263 {
264 test_interface_method_call,
265 test_interface_get_property,
266 NULL, /* set_property */
267 { 0 }
268 };
269
270 static void
271 on_proxy_signal_received (GDBusProxy *proxy,
272 gchar *sender_name,
273 gchar *signal_name,
274 GVariant *parameters,
275 gpointer user_data)
276 {
277 PeerData *data = user_data;
278
279 data->signal_received = TRUE;
280
281 g_assert (sender_name == NULL);
282 g_assert_cmpstr (signal_name, ==, "PeerSignal");
283 g_main_loop_quit (loop);
284 }
285
286 static void
287 on_proxy_signal_received_with_name_set (GDBusProxy *proxy,
288 gchar *sender_name,
289 gchar *signal_name,
290 GVariant *parameters,
291 gpointer user_data)
292 {
293 PeerData *data = user_data;
294
295 data->signal_received = TRUE;
296
297 g_assert_cmpstr (sender_name, ==, ":1.42");
298 g_assert_cmpstr (signal_name, ==, "PeerSignalWithNameSet");
299 g_main_loop_quit (loop);
300 }
301
302 /* ---------------------------------------------------------------------------------------------------- */
303
304 static gboolean
305 af_unix_works (void)
306 {
307 int fd;
308
309 g_networking_init ();
310 fd = socket (AF_UNIX, SOCK_STREAM, 0);
311
312 #ifdef G_OS_WIN32
313 closesocket (fd);
314 return fd != (int) INVALID_SOCKET;
315 #else
316 g_close (fd, NULL);
317 return fd >= 0;
318 #endif
319 }
320
321 static void
322 setup_test_address (void)
323 {
324 if (is_unix || af_unix_works ())
325 {
326 g_test_message ("Testing with unix:dir address");
327 tmpdir = g_dir_make_tmp ("gdbus-test-XXXXXX", NULL);
328 tmp_address = g_strdup_printf ("unix:dir=%s", tmpdir);
329 }
330 else
331 tmp_address = g_strdup ("nonce-tcp:host=127.0.0.1");
332 }
333
334 #ifdef G_OS_UNIX
335 static void
336 setup_tmpdir_test_address (void)
337 {
338 g_test_message ("Testing with unix:tmpdir address");
339 tmpdir = g_dir_make_tmp ("gdbus-test-XXXXXX", NULL);
340 tmp_address = g_strdup_printf ("unix:tmpdir=%s", tmpdir);
341 }
342
343 static void
344 setup_path_test_address (void)
345 {
346 g_test_message ("Testing with unix:path address");
347 tmpdir = g_dir_make_tmp ("gdbus-test-XXXXXX", NULL);
348 tmp_address = g_strdup_printf ("unix:path=%s/gdbus-peer-socket", tmpdir);
349 }
350 #endif
351
352 static void
353 teardown_test_address (void)
354 {
355 g_free (tmp_address);
356 if (tmpdir)
357 {
358 /* Ensuring the rmdir succeeds also ensures any sockets created on the
359 * filesystem are also deleted.
360 */
361 g_assert_cmpstr (g_rmdir (tmpdir) == 0 ? "OK" : g_strerror (errno),
362 ==, "OK");
363 g_clear_pointer (&tmpdir, g_free);
364 }
365 }
366
367 /* ---------------------------------------------------------------------------------------------------- */
368
369 static gboolean
370 on_authorize_authenticated_peer (GDBusAuthObserver *observer,
371 GIOStream *stream,
372 GCredentials *credentials,
373 gpointer user_data)
374 {
375 PeerData *data = user_data;
376 gboolean authorized;
377
378 data->num_connection_attempts++;
379
380 authorized = TRUE;
381 if (!data->accept_connection)
382 {
383 authorized = FALSE;
384 g_main_loop_quit (loop);
385 }
386
387 return authorized;
388 }
389
390 /* Runs in thread we created GDBusServer in (since we didn't pass G_DBUS_SERVER_FLAGS_RUN_IN_THREAD) */
391 static gboolean
392 on_new_connection (GDBusServer *server,
393 GDBusConnection *connection,
394 gpointer user_data)
395 {
396 PeerData *data = user_data;
397 GError *error = NULL;
398 guint reg_id;
399
400 //g_printerr ("Client connected.\n"
401 // "Negotiated capabilities: unix-fd-passing=%d\n",
402 // g_dbus_connection_get_capabilities (connection) & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING);
403
404 g_ptr_array_add (data->current_connections, g_object_ref (connection));
405
406 #if G_CREDENTIALS_SUPPORTED
407 {
408 GCredentials *credentials;
409
410 credentials = g_dbus_connection_get_peer_credentials (connection);
411
412 g_assert (credentials != NULL);
413 #ifdef G_OS_WIN32
414 {
415 DWORD *pid;
416 pid = g_credentials_get_native (credentials, G_CREDENTIALS_TYPE_WIN32_PID);
417 g_assert_cmpuint (*pid, ==, GetCurrentProcessId ());
418 }
419 #else
420 g_assert_cmpuint (g_credentials_get_unix_user (credentials, NULL), ==,
421 getuid ());
422 #if G_CREDENTIALS_HAS_PID
423 g_assert_cmpint (g_credentials_get_unix_pid (credentials, &error), ==,
424 getpid ());
425 g_assert_no_error (error);
426 #else
427 g_assert_cmpint (g_credentials_get_unix_pid (credentials, &error), ==, -1);
428 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
429 g_clear_error (&error);
430 #endif /* G_CREDENTIALS_HAS_PID */
431 #endif /* G_OS_WIN32 */
432 }
433 #endif /* G_CREDENTIALS_SUPPORTED */
434
435 /* export object on the newly established connection */
436 reg_id = g_dbus_connection_register_object (connection,
437 "/org/gtk/GDBus/PeerTestObject",
438 test_interface_introspection_data,
439 &test_interface_vtable,
440 data,
441 NULL, /* GDestroyNotify for data */
442 &error);
443 g_assert_no_error (error);
444 g_assert (reg_id > 0);
445
446 g_main_loop_quit (loop);
447
448 return TRUE;
449 }
450
451 /* We don't tell the main thread about the new GDBusServer until it has
452 * had a chance to start listening. */
453 static gboolean
454 idle_in_service_loop (gpointer loop)
455 {
456 g_assert (service_loop == NULL);
457 g_mutex_lock (&service_loop_lock);
458 service_loop = loop;
459 g_cond_broadcast (&service_loop_cond);
460 g_mutex_unlock (&service_loop_lock);
461
462 return G_SOURCE_REMOVE;
463 }
464
465 static void
466 run_service_loop (GMainContext *service_context)
467 {
468 GMainLoop *loop;
469 GSource *source;
470
471 g_assert (service_loop == NULL);
472
473 loop = g_main_loop_new (service_context, FALSE);
474 source = g_idle_source_new ();
475 g_source_set_callback (source, idle_in_service_loop, loop, NULL);
476 g_source_attach (source, service_context);
477 g_source_unref (source);
478 g_main_loop_run (loop);
479 }
480
481 static void
482 teardown_service_loop (void)
483 {
484 g_mutex_lock (&service_loop_lock);
485 g_clear_pointer (&service_loop, g_main_loop_unref);
486 g_mutex_unlock (&service_loop_lock);
487 }
488
489 static void
490 await_service_loop (void)
491 {
492 g_mutex_lock (&service_loop_lock);
493 while (service_loop == NULL)
494 g_cond_wait (&service_loop_cond, &service_loop_lock);
495 g_mutex_unlock (&service_loop_lock);
496 }
497
498 static gpointer
499 service_thread_func (gpointer user_data)
500 {
501 PeerData *data = user_data;
502 GMainContext *service_context;
503 GDBusAuthObserver *observer, *o;
504 GError *error;
505 GDBusServerFlags f;
506 gchar *a, *g;
507 gboolean b;
508
509 service_context = g_main_context_new ();
510 g_main_context_push_thread_default (service_context);
511
512 error = NULL;
513 observer = g_dbus_auth_observer_new ();
514 server = g_dbus_server_new_sync (tmp_address,
515 G_DBUS_SERVER_FLAGS_NONE,
516 test_guid,
517 observer,
518 NULL, /* cancellable */
519 &error);
520 g_assert_no_error (error);
521
522 g_signal_connect (server,
523 "new-connection",
524 G_CALLBACK (on_new_connection),
525 data);
526 g_signal_connect (observer,
527 "authorize-authenticated-peer",
528 G_CALLBACK (on_authorize_authenticated_peer),
529 data);
530
531 g_assert_cmpint (g_dbus_server_get_flags (server), ==, G_DBUS_SERVER_FLAGS_NONE);
532 g_assert_cmpstr (g_dbus_server_get_guid (server), ==, test_guid);
533 g_object_get (server,
534 "flags", &f,
535 "address", &a,
536 "guid", &g,
537 "active", &b,
538 "authentication-observer", &o,
539 NULL);
540 g_assert_cmpint (f, ==, G_DBUS_SERVER_FLAGS_NONE);
541 g_assert_cmpstr (a, ==, tmp_address);
542 g_assert_cmpstr (g, ==, test_guid);
543 g_assert (!b);
544 g_assert (o == observer);
545 g_free (a);
546 g_free (g);
547 g_object_unref (o);
548
549 g_object_unref (observer);
550
551 g_dbus_server_start (server);
552
553 run_service_loop (service_context);
554
555 g_main_context_pop_thread_default (service_context);
556
557 teardown_service_loop ();
558 g_main_context_unref (service_context);
559
560 /* test code specifically unrefs the server - see below */
561 g_assert (server == NULL);
562
563 return NULL;
564 }
565
566 #if 0
567 static gboolean
568 on_incoming_connection (GSocketService *service,
569 GSocketConnection *socket_connection,
570 GObject *source_object,
571 gpointer user_data)
572 {
573 PeerData *data = user_data;
574
575 if (data->accept_connection)
576 {
577 GError *error;
578 guint reg_id;
579 GDBusConnection *connection;
580
581 error = NULL;
582 connection = g_dbus_connection_new_sync (G_IO_STREAM (socket_connection),
583 test_guid,
584 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER,
585 NULL, /* cancellable */
586 &error);
587 g_assert_no_error (error);
588
589 g_ptr_array_add (data->current_connections, connection);
590
591 /* export object on the newly established connection */
592 error = NULL;
593 reg_id = g_dbus_connection_register_object (connection,
594 "/org/gtk/GDBus/PeerTestObject",
595 &test_interface_introspection_data,
596 &test_interface_vtable,
597 data,
598 NULL, /* GDestroyNotify for data */
599 &error);
600 g_assert_no_error (error);
601 g_assert (reg_id > 0);
602
603 }
604 else
605 {
606 /* don't do anything */
607 }
608
609 data->num_connection_attempts++;
610
611 g_main_loop_quit (loop);
612
613 /* stops other signal handlers from being invoked */
614 return TRUE;
615 }
616
617 static gpointer
618 service_thread_func (gpointer data)
619 {
620 GMainContext *service_context;
621 gchar *socket_path;
622 GSocketAddress *address;
623 GError *error;
624
625 service_context = g_main_context_new ();
626 g_main_context_push_thread_default (service_context);
627
628 socket_path = g_strdup_printf ("/tmp/gdbus-test-pid-%d", getpid ());
629 address = g_unix_socket_address_new (socket_path);
630
631 service = g_socket_service_new ();
632 error = NULL;
633 g_socket_listener_add_address (G_SOCKET_LISTENER (service),
634 address,
635 G_SOCKET_TYPE_STREAM,
636 G_SOCKET_PROTOCOL_DEFAULT,
637 NULL, /* source_object */
638 NULL, /* effective_address */
639 &error);
640 g_assert_no_error (error);
641 g_signal_connect (service,
642 "incoming",
643 G_CALLBACK (on_incoming_connection),
644 data);
645 g_socket_service_start (service);
646
647 run_service_loop (service_context);
648
649 g_main_context_pop_thread_default (service_context);
650
651 teardown_service_loop ();
652 g_main_context_unref (service_context);
653
654 g_object_unref (address);
655 g_free (socket_path);
656 return NULL;
657 }
658 #endif
659
660 /* ---------------------------------------------------------------------------------------------------- */
661
662 #if 0
663 static gboolean
664 check_connection (gpointer user_data)
665 {
666 PeerData *data = user_data;
667 guint n;
668
669 for (n = 0; n < data->current_connections->len; n++)
670 {
671 GDBusConnection *c;
672 GIOStream *stream;
673
674 c = G_DBUS_CONNECTION (data->current_connections->pdata[n]);
675 stream = g_dbus_connection_get_stream (c);
676
677 g_debug ("In check_connection for %d: connection %p, stream %p", n, c, stream);
678 g_debug ("closed = %d", g_io_stream_is_closed (stream));
679
680 GSocket *socket;
681 socket = g_socket_connection_get_socket (G_SOCKET_CONNECTION (stream));
682 g_debug ("socket_closed = %d", g_socket_is_closed (socket));
683 g_debug ("socket_condition_check = %d", g_socket_condition_check (socket, G_IO_IN|G_IO_OUT|G_IO_ERR|G_IO_HUP));
684
685 gchar buf[128];
686 GError *error;
687 gssize num_read;
688 error = NULL;
689 num_read = g_input_stream_read (g_io_stream_get_input_stream (stream),
690 buf,
691 128,
692 NULL,
693 &error);
694 if (num_read < 0)
695 {
696 g_debug ("error: %s", error->message);
697 g_error_free (error);
698 }
699 else
700 {
701 g_debug ("no error, read %d bytes", (gint) num_read);
702 }
703 }
704
705 return G_SOURCE_REMOVE;
706 }
707
708 static gboolean
709 on_do_disconnect_in_idle (gpointer data)
710 {
711 GDBusConnection *c = G_DBUS_CONNECTION (data);
712 g_debug ("GDC %p has ref_count %d", c, G_OBJECT (c)->ref_count);
713 g_dbus_connection_disconnect (c);
714 g_object_unref (c);
715 return G_SOURCE_REMOVE;
716 }
717 #endif
718
719 #ifdef G_OS_UNIX
720 static gchar *
721 read_all_from_fd (gint fd, gsize *out_len, GError **error)
722 {
723 GString *str;
724 gchar buf[64];
725 gssize num_read;
726
727 str = g_string_new (NULL);
728
729 do
730 {
731 int errsv;
732
733 num_read = read (fd, buf, sizeof (buf));
734 errsv = errno;
735 if (num_read == -1)
736 {
737 if (errsv == EAGAIN || errsv == EWOULDBLOCK)
738 continue;
739 g_set_error (error,
740 G_IO_ERROR,
741 g_io_error_from_errno (errsv),
742 "Failed reading %d bytes into offset %d: %s",
743 (gint) sizeof (buf),
744 (gint) str->len,
745 g_strerror (errsv));
746 goto error;
747 }
748 else if (num_read > 0)
749 {
750 g_string_append_len (str, buf, num_read);
751 }
752 else if (num_read == 0)
753 {
754 break;
755 }
756 }
757 while (TRUE);
758
759 if (out_len != NULL)
760 *out_len = str->len;
761 return g_string_free (str, FALSE);
762
763 error:
764 if (out_len != NULL)
765 *out_len = 0;
766 g_string_free (str, TRUE);
767 return NULL;
768 }
769 #endif
770
771 static void
772 do_test_peer (void)
773 {
774 GDBusConnection *c;
775 GDBusConnection *c2;
776 GDBusProxy *proxy;
777 GError *error;
778 PeerData data;
779 GVariant *value;
780 GVariant *result;
781 const gchar *s;
782 GThread *service_thread;
783 gulong signal_handler_id;
784 gsize i;
785
786 memset (&data, '\0', sizeof (PeerData));
787 data.current_connections = g_ptr_array_new_with_free_func (g_object_unref);
788
789 /* first try to connect when there is no server */
790 error = NULL;
791 c = g_dbus_connection_new_for_address_sync (is_unix ? "unix:path=/tmp/gdbus-test-does-not-exist-pid" :
792 /* NOTE: Even if something is listening on port 12345 the connection
793 * will fail because the nonce file doesn't exist */
794 "nonce-tcp:host=127.0.0.1,port=12345,noncefile=this-does-not-exist-gdbus",
795 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
796 NULL, /* GDBusAuthObserver */
797 NULL, /* cancellable */
798 &error);
799 _g_assert_error_domain (error, G_IO_ERROR);
800 g_assert (!g_dbus_error_is_remote_error (error));
801 g_clear_error (&error);
802 g_assert (c == NULL);
803
804 /* bring up a server - we run the server in a different thread to avoid deadlocks */
805 service_thread = g_thread_new ("test_peer",
806 service_thread_func,
807 &data);
808 await_service_loop ();
809 g_assert (server != NULL);
810
811 /* bring up a connection and accept it */
812 data.accept_connection = TRUE;
813 error = NULL;
814 c = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (server),
815 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
816 NULL, /* GDBusAuthObserver */
817 NULL, /* cancellable */
818 &error);
819 g_assert_no_error (error);
820 g_assert (c != NULL);
821 while (data.current_connections->len < 1)
822 g_main_loop_run (loop);
823 g_assert_cmpint (data.current_connections->len, ==, 1);
824 g_assert_cmpint (data.num_connection_attempts, ==, 1);
825 g_assert (g_dbus_connection_get_unique_name (c) == NULL);
826 g_assert_cmpstr (g_dbus_connection_get_guid (c), ==, test_guid);
827
828 /* check that we create a proxy, read properties, receive signals and invoke
829 * the HelloPeer() method. Since the server runs in another thread it's fine
830 * to use synchronous blocking API here.
831 */
832 error = NULL;
833 proxy = g_dbus_proxy_new_sync (c,
834 G_DBUS_PROXY_FLAGS_NONE,
835 NULL,
836 NULL, /* bus_name */
837 "/org/gtk/GDBus/PeerTestObject",
838 "org.gtk.GDBus.PeerTestInterface",
839 NULL, /* GCancellable */
840 &error);
841 g_assert_no_error (error);
842 g_assert (proxy != NULL);
843 error = NULL;
844 value = g_dbus_proxy_get_cached_property (proxy, "PeerProperty");
845 g_assert_cmpstr (g_variant_get_string (value, NULL), ==, "ThePropertyValue");
846 g_clear_pointer (&value, g_variant_unref);
847
848 /* try invoking a method */
849 error = NULL;
850 result = g_dbus_proxy_call_sync (proxy,
851 "HelloPeer",
852 g_variant_new ("(s)", "Hey Peer!"),
853 G_DBUS_CALL_FLAGS_NONE,
854 -1,
855 NULL, /* GCancellable */
856 &error);
857 g_assert_no_error (error);
858 g_variant_get (result, "(&s)", &s);
859 g_assert_cmpstr (s, ==, "You greeted me with 'Hey Peer!'.");
860 g_variant_unref (result);
861 g_assert_cmpint (data.num_method_calls, ==, 1);
862
863 /* make the other peer emit a signal - catch it */
864 signal_handler_id = g_signal_connect (proxy,
865 "g-signal",
866 G_CALLBACK (on_proxy_signal_received),
867 &data);
868 g_assert (!data.signal_received);
869 g_dbus_proxy_call (proxy,
870 "EmitSignal",
871 NULL, /* no arguments */
872 G_DBUS_CALL_FLAGS_NONE,
873 -1,
874 NULL, /* GCancellable */
875 NULL, /* GAsyncReadyCallback - we don't care about the result */
876 NULL); /* user_data */
877 g_main_loop_run (loop);
878 g_assert (data.signal_received);
879 g_assert_cmpint (data.num_method_calls, ==, 2);
880 g_signal_handler_disconnect (proxy, signal_handler_id);
881
882 /* Also ensure that messages with the sender header-field set gets
883 * delivered to the proxy - note that this doesn't really make sense
884 * e.g. names are meaning-less in a peer-to-peer case... but we
885 * support it because it makes sense in certain bridging
886 * applications - see e.g. #623815.
887 */
888 signal_handler_id = g_signal_connect (proxy,
889 "g-signal",
890 G_CALLBACK (on_proxy_signal_received_with_name_set),
891 &data);
892 data.signal_received = FALSE;
893 g_dbus_proxy_call (proxy,
894 "EmitSignalWithNameSet",
895 NULL, /* no arguments */
896 G_DBUS_CALL_FLAGS_NONE,
897 -1,
898 NULL, /* GCancellable */
899 NULL, /* GAsyncReadyCallback - we don't care about the result */
900 NULL); /* user_data */
901 g_main_loop_run (loop);
902 g_assert (data.signal_received);
903 g_assert_cmpint (data.num_method_calls, ==, 3);
904 g_signal_handler_disconnect (proxy, signal_handler_id);
905
906 /*
907 * Check for UNIX fd passing.
908 *
909 * The first time through, we use a very simple method call. Note that
910 * because this does not have a G_VARIANT_TYPE_HANDLE in the message body
911 * to refer to the fd, it is a GDBus-specific idiom that would not
912 * interoperate with libdbus or sd-bus
913 * (see <https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1726>).
914 *
915 * The second time, we call a method that returns a fd attached to a
916 * large message, to reproduce
917 * <https://gitlab.gnome.org/GNOME/glib/-/issues/2074>. It also happens
918 * to follow the more usual pattern for D-Bus messages containing a
919 * G_VARIANT_TYPE_HANDLE to refer to attached fds.
920 */
921 for (i = 0; i < 2; i++)
922 {
923 #ifdef G_OS_UNIX
924 GDBusMessage *method_call_message;
925 GDBusMessage *method_reply_message;
926 GUnixFDList *fd_list;
927 gint fd;
928 gchar *buf;
929 gsize len;
930 gchar *buf2;
931 gsize len2;
932 const char *testfile = g_test_get_filename (G_TEST_DIST, "file.c", NULL);
933 const char *method = "OpenFile";
934 GVariant *body;
935
936 if (i == 1)
937 method = "OpenFileWithBigMessage";
938
939 method_call_message = g_dbus_message_new_method_call (NULL, /* name */
940 "/org/gtk/GDBus/PeerTestObject",
941 "org.gtk.GDBus.PeerTestInterface",
942 method);
943 g_dbus_message_set_body (method_call_message, g_variant_new ("(s)", testfile));
944 error = NULL;
945 method_reply_message = g_dbus_connection_send_message_with_reply_sync (c,
946 method_call_message,
947 G_DBUS_SEND_MESSAGE_FLAGS_NONE,
948 -1,
949 NULL, /* out_serial */
950 NULL, /* cancellable */
951 &error);
952 g_assert_no_error (error);
953 g_assert (g_dbus_message_get_message_type (method_reply_message) == G_DBUS_MESSAGE_TYPE_METHOD_RETURN);
954
955 body = g_dbus_message_get_body (method_reply_message);
956
957 if (i == 1)
958 {
959 gint32 handle = -1;
960 GVariant *junk = NULL;
961
962 g_assert_cmpstr (g_variant_get_type_string (body), ==, "(hay)");
963 g_variant_get (body, "(h@ay)", &handle, &junk);
964 g_assert_cmpint (handle, ==, 0);
965 g_assert_cmpuint (g_variant_n_children (junk), ==, BIG_MESSAGE_ARRAY_SIZE);
966 g_variant_unref (junk);
967 }
968 else
969 {
970 g_assert_null (body);
971 }
972
973 fd_list = g_dbus_message_get_unix_fd_list (method_reply_message);
974 g_assert (fd_list != NULL);
975 g_assert_cmpint (g_unix_fd_list_get_length (fd_list), ==, 1);
976 error = NULL;
977 fd = g_unix_fd_list_get (fd_list, 0, &error);
978 g_assert_no_error (error);
979 g_object_unref (method_call_message);
980 g_object_unref (method_reply_message);
981
982 error = NULL;
983 len = 0;
984 buf = read_all_from_fd (fd, &len, &error);
985 g_assert_no_error (error);
986 g_assert (buf != NULL);
987 close (fd);
988
989 error = NULL;
990 g_file_get_contents (testfile,
991 &buf2,
992 &len2,
993 &error);
994 g_assert_no_error (error);
995 g_assert_cmpmem (buf, len, buf2, len2);
996 g_free (buf2);
997 g_free (buf);
998 #else
999 /* We do the same number of iterations on non-Unix, so that
1000 * the method call count will match. In this case we use
1001 * OpenFile both times, because the difference between this
1002 * and OpenFileWithBigMessage is only relevant on Unix. */
1003 error = NULL;
1004 result = g_dbus_proxy_call_sync (proxy,
1005 "OpenFile",
1006 g_variant_new ("(s)", "boo"),
1007 G_DBUS_CALL_FLAGS_NONE,
1008 -1,
1009 NULL, /* GCancellable */
1010 &error);
1011 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR);
1012 g_assert (result == NULL);
1013 g_error_free (error);
1014 #endif /* G_OS_UNIX */
1015 }
1016
1017 /* Check that g_socket_get_credentials() work - (though this really
1018 * should be in socket.c)
1019 */
1020 {
1021 GSocket *socket;
1022 GCredentials *credentials;
1023 socket = g_socket_connection_get_socket (G_SOCKET_CONNECTION (g_dbus_connection_get_stream (c)));
1024 g_assert (G_IS_SOCKET (socket));
1025 error = NULL;
1026 credentials = g_socket_get_credentials (socket, &error);
1027
1028 #if G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED
1029 g_assert_no_error (error);
1030 g_assert (G_IS_CREDENTIALS (credentials));
1031
1032 #ifdef G_OS_WIN32
1033 {
1034 DWORD *pid;
1035 pid = g_credentials_get_native (credentials, G_CREDENTIALS_TYPE_WIN32_PID);
1036 g_assert_cmpuint (*pid, ==, GetCurrentProcessId ());
1037 }
1038 #else
1039 g_assert_cmpuint (g_credentials_get_unix_user (credentials, NULL), ==,
1040 getuid ());
1041 #if G_CREDENTIALS_HAS_PID
1042 g_assert_cmpint (g_credentials_get_unix_pid (credentials, &error), ==,
1043 getpid ());
1044 g_assert_no_error (error);
1045 #else
1046 g_assert_cmpint (g_credentials_get_unix_pid (credentials, &error), ==, -1);
1047 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
1048 g_clear_error (&error);
1049 #endif /* G_CREDENTIALS_HAS_PID */
1050 g_object_unref (credentials);
1051 #endif /* G_OS_WIN32 */
1052 #else
1053 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
1054 g_assert (credentials == NULL);
1055 #endif /* G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED */
1056 }
1057
1058
1059 /* bring up a connection - don't accept it - this should fail
1060 */
1061 data.accept_connection = FALSE;
1062 error = NULL;
1063 c2 = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (server),
1064 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1065 NULL, /* GDBusAuthObserver */
1066 NULL, /* cancellable */
1067 &error);
1068 _g_assert_error_domain (error, G_IO_ERROR);
1069 g_error_free (error);
1070 g_assert (c2 == NULL);
1071
1072 #if 0
1073 /* TODO: THIS TEST DOESN'T WORK YET */
1074
1075 /* bring up a connection - accept it.. then disconnect from the client side - check
1076 * that the server side gets the disconnect signal.
1077 */
1078 error = NULL;
1079 data.accept_connection = TRUE;
1080 c2 = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (server),
1081 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1082 NULL, /* GDBusAuthObserver */
1083 NULL, /* cancellable */
1084 &error);
1085 g_assert_no_error (error);
1086 g_assert (c2 != NULL);
1087 g_assert (!g_dbus_connection_get_is_disconnected (c2));
1088 while (data.num_connection_attempts < 3)
1089 g_main_loop_run (loop);
1090 g_assert_cmpint (data.current_connections->len, ==, 2);
1091 g_assert_cmpint (data.num_connection_attempts, ==, 3);
1092 g_assert (!g_dbus_connection_get_is_disconnected (G_DBUS_CONNECTION (data.current_connections->pdata[1])));
1093 g_idle_add (on_do_disconnect_in_idle, c2);
1094 g_debug ("==================================================");
1095 g_debug ("==================================================");
1096 g_debug ("==================================================");
1097 g_debug ("waiting for disconnect on connection %p, stream %p",
1098 data.current_connections->pdata[1],
1099 g_dbus_connection_get_stream (data.current_connections->pdata[1]));
1100
1101 g_timeout_add (2000, check_connection, &data);
1102 //_g_assert_signal_received (G_DBUS_CONNECTION (data.current_connections->pdata[1]), "closed");
1103 g_main_loop_run (loop);
1104 g_assert (g_dbus_connection_get_is_disconnected (G_DBUS_CONNECTION (data.current_connections->pdata[1])));
1105 g_ptr_array_set_size (data.current_connections, 1); /* remove disconnected connection object */
1106 #endif
1107
1108 /* unref the server and stop listening for new connections
1109 *
1110 * This won't bring down the established connections - check that c is still connected
1111 * by invoking a method
1112 */
1113 //g_socket_service_stop (service);
1114 //g_object_unref (service);
1115 g_dbus_server_stop (server);
1116 g_object_unref (server);
1117 server = NULL;
1118
1119 error = NULL;
1120 result = g_dbus_proxy_call_sync (proxy,
1121 "HelloPeer",
1122 g_variant_new ("(s)", "Hey Again Peer!"),
1123 G_DBUS_CALL_FLAGS_NONE,
1124 -1,
1125 NULL, /* GCancellable */
1126 &error);
1127 g_assert_no_error (error);
1128 g_variant_get (result, "(&s)", &s);
1129 g_assert_cmpstr (s, ==, "You greeted me with 'Hey Again Peer!'.");
1130 g_variant_unref (result);
1131 g_assert_cmpint (data.num_method_calls, ==, 6);
1132
1133 #if 0
1134 /* TODO: THIS TEST DOESN'T WORK YET */
1135
1136 /* now disconnect from the server side - check that the client side gets the signal */
1137 g_assert_cmpint (data.current_connections->len, ==, 1);
1138 g_assert (G_DBUS_CONNECTION (data.current_connections->pdata[0]) != c);
1139 g_dbus_connection_disconnect (G_DBUS_CONNECTION (data.current_connections->pdata[0]));
1140 if (!g_dbus_connection_get_is_disconnected (c))
1141 _g_assert_signal_received (c, "closed");
1142 g_assert (g_dbus_connection_get_is_disconnected (c));
1143 #endif
1144
1145 g_object_unref (c);
1146 g_ptr_array_unref (data.current_connections);
1147 g_object_unref (proxy);
1148
1149 g_main_loop_quit (service_loop);
1150 g_thread_join (service_thread);
1151 }
1152
1153 static void
1154 test_peer (void)
1155 {
1156 test_guid = g_dbus_generate_guid ();
1157 loop = g_main_loop_new (NULL, FALSE);
1158
1159 /* Run this test multiple times using different address formats to ensure
1160 * they all work.
1161 */
1162 setup_test_address ();
1163 do_test_peer ();
1164 teardown_test_address ();
1165
1166 #ifdef G_OS_UNIX
1167 setup_tmpdir_test_address ();
1168 do_test_peer ();
1169 teardown_test_address ();
1170
1171 setup_path_test_address ();
1172 do_test_peer ();
1173 teardown_test_address ();
1174 #endif
1175
1176 g_main_loop_unref (loop);
1177 g_free (test_guid);
1178 }
1179
1180 /* ---------------------------------------------------------------------------------------------------- */
1181
1182 #define VALID_GUID "0123456789abcdef0123456789abcdef"
1183
1184 static void
1185 test_peer_invalid_server (void)
1186 {
1187 GDBusServer *server;
1188
1189 if (!g_test_undefined ())
1190 {
1191 g_test_skip ("Not exercising programming errors");
1192 return;
1193 }
1194
1195 if (g_test_subprocess ())
1196 {
1197 /* This assumes we are not going to run out of GDBusServerFlags
1198 * any time soon */
1199 server = g_dbus_server_new_sync ("tcp:", (GDBusServerFlags) (1 << 30),
1200 VALID_GUID,
1201 NULL, NULL, NULL);
1202 g_assert_null (server);
1203 }
1204 else
1205 {
1206 g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_DEFAULT);
1207 g_test_trap_assert_failed ();
1208 g_test_trap_assert_stderr ("*CRITICAL*G_DBUS_SERVER_FLAGS_ALL*");
1209 }
1210 }
1211
1212 static void
1213 test_peer_invalid_conn_stream_sync (void)
1214 {
1215 GSocket *sock;
1216 GSocketConnection *socket_conn;
1217 GIOStream *iostream;
1218 GDBusConnection *conn;
1219
1220 if (!g_test_undefined ())
1221 {
1222 g_test_skip ("Not exercising programming errors");
1223 return;
1224 }
1225
1226 sock = g_socket_new (G_SOCKET_FAMILY_IPV4,
1227 G_SOCKET_TYPE_STREAM,
1228 G_SOCKET_PROTOCOL_TCP,
1229 NULL);
1230
1231 if (sock == NULL)
1232 {
1233 g_test_skip ("TCP not available?");
1234 return;
1235 }
1236
1237 socket_conn = g_socket_connection_factory_create_connection (sock);
1238 g_assert_nonnull (socket_conn);
1239 iostream = G_IO_STREAM (socket_conn);
1240 g_assert_nonnull (iostream);
1241
1242 if (g_test_subprocess ())
1243 {
1244 /* This assumes we are not going to run out of GDBusConnectionFlags
1245 * any time soon */
1246 conn = g_dbus_connection_new_sync (iostream, VALID_GUID,
1247 (GDBusConnectionFlags) (1 << 30),
1248 NULL, NULL, NULL);
1249 g_assert_null (conn);
1250 }
1251 else
1252 {
1253 g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_DEFAULT);
1254 g_test_trap_assert_failed ();
1255 g_test_trap_assert_stderr ("*CRITICAL*G_DBUS_CONNECTION_FLAGS_ALL*");
1256 }
1257
1258 g_clear_object (&sock);
1259 g_clear_object (&socket_conn);
1260 }
1261
1262 static void
1263 test_peer_invalid_conn_stream_async (void)
1264 {
1265 GSocket *sock;
1266 GSocketConnection *socket_conn;
1267 GIOStream *iostream;
1268
1269 if (!g_test_undefined ())
1270 {
1271 g_test_skip ("Not exercising programming errors");
1272 return;
1273 }
1274
1275 sock = g_socket_new (G_SOCKET_FAMILY_IPV4,
1276 G_SOCKET_TYPE_STREAM,
1277 G_SOCKET_PROTOCOL_TCP,
1278 NULL);
1279
1280 if (sock == NULL)
1281 {
1282 g_test_skip ("TCP not available?");
1283 return;
1284 }
1285
1286 socket_conn = g_socket_connection_factory_create_connection (sock);
1287 g_assert_nonnull (socket_conn);
1288 iostream = G_IO_STREAM (socket_conn);
1289 g_assert_nonnull (iostream);
1290
1291 if (g_test_subprocess ())
1292 {
1293 g_dbus_connection_new (iostream, VALID_GUID,
1294 (GDBusConnectionFlags) (1 << 30),
1295 NULL, NULL, NULL, NULL);
1296 }
1297 else
1298 {
1299 g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_DEFAULT);
1300 g_test_trap_assert_failed ();
1301 g_test_trap_assert_stderr ("*CRITICAL*G_DBUS_CONNECTION_FLAGS_ALL*");
1302 }
1303
1304 g_clear_object (&sock);
1305 g_clear_object (&socket_conn);
1306 }
1307
1308 static void
1309 test_peer_invalid_conn_addr_sync (void)
1310 {
1311 GDBusConnection *conn;
1312
1313 if (!g_test_undefined ())
1314 {
1315 g_test_skip ("Not exercising programming errors");
1316 return;
1317 }
1318
1319 if (g_test_subprocess ())
1320 {
1321 conn = g_dbus_connection_new_for_address_sync ("tcp:",
1322 (GDBusConnectionFlags) (1 << 30),
1323 NULL, NULL, NULL);
1324 g_assert_null (conn);
1325 }
1326 else
1327 {
1328 g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_DEFAULT);
1329 g_test_trap_assert_failed ();
1330 g_test_trap_assert_stderr ("*CRITICAL*G_DBUS_CONNECTION_FLAGS_ALL*");
1331 }
1332 }
1333
1334 static void
1335 test_peer_invalid_conn_addr_async (void)
1336 {
1337 if (!g_test_undefined ())
1338 {
1339 g_test_skip ("Not exercising programming errors");
1340 return;
1341 }
1342
1343 if (g_test_subprocess ())
1344 {
1345 g_dbus_connection_new_for_address ("tcp:",
1346 (GDBusConnectionFlags) (1 << 30),
1347 NULL, NULL, NULL, NULL);
1348 }
1349 else
1350 {
1351 g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_DEFAULT);
1352 g_test_trap_assert_failed ();
1353 g_test_trap_assert_stderr ("*CRITICAL*G_DBUS_CONNECTION_FLAGS_ALL*");
1354 }
1355 }
1356
1357 /* ---------------------------------------------------------------------------------------------------- */
1358
1359 static void
1360 test_peer_signals (void)
1361 {
1362 GDBusConnection *c;
1363 GDBusProxy *proxy;
1364 GError *error = NULL;
1365 PeerData data;
1366 GThread *service_thread;
1367
1368 g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/1620");
1369
1370 test_guid = g_dbus_generate_guid ();
1371 loop = g_main_loop_new (NULL, FALSE);
1372
1373 setup_test_address ();
1374 memset (&data, '\0', sizeof (PeerData));
1375 data.current_connections = g_ptr_array_new_with_free_func (g_object_unref);
1376
1377 /* bring up a server - we run the server in a different thread to avoid deadlocks */
1378 service_thread = g_thread_new ("test_peer",
1379 service_thread_func,
1380 &data);
1381 await_service_loop ();
1382 g_assert_nonnull (server);
1383
1384 /* bring up a connection and accept it */
1385 data.accept_connection = TRUE;
1386 c = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (server),
1387 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1388 NULL, /* GDBusAuthObserver */
1389 NULL, /* cancellable */
1390 &error);
1391 g_assert_no_error (error);
1392 g_assert_nonnull (c);
1393 while (data.current_connections->len < 1)
1394 g_main_loop_run (loop);
1395 g_assert_cmpint (data.current_connections->len, ==, 1);
1396 g_assert_cmpint (data.num_connection_attempts, ==, 1);
1397 g_assert_null (g_dbus_connection_get_unique_name (c));
1398 g_assert_cmpstr (g_dbus_connection_get_guid (c), ==, test_guid);
1399
1400 /* Check that we can create a proxy with a non-NULL bus name, even though it's
1401 * irrelevant in the non-message-bus case. Since the server runs in another
1402 * thread it's fine to use synchronous blocking API here.
1403 */
1404 proxy = g_dbus_proxy_new_sync (c,
1405 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
1406 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
1407 NULL,
1408 ":1.1", /* bus_name */
1409 "/org/gtk/GDBus/PeerTestObject",
1410 "org.gtk.GDBus.PeerTestInterface",
1411 NULL, /* GCancellable */
1412 &error);
1413 g_assert_no_error (error);
1414 g_assert_nonnull (proxy);
1415
1416 /* unref the server and stop listening for new connections */
1417 g_dbus_server_stop (server);
1418 g_clear_object (&server);
1419
1420 g_object_unref (c);
1421 g_ptr_array_unref (data.current_connections);
1422 g_object_unref (proxy);
1423
1424 g_main_loop_quit (service_loop);
1425 g_thread_join (service_thread);
1426
1427 teardown_test_address ();
1428
1429 g_main_loop_unref (loop);
1430 g_free (test_guid);
1431 }
1432
1433 /* ---------------------------------------------------------------------------------------------------- */
1434
1435 typedef struct
1436 {
1437 GDBusServer *server;
1438 GMainContext *context;
1439 GMainLoop *loop;
1440
1441 GList *connections;
1442 } DmpData;
1443
1444 static void
1445 dmp_data_free (DmpData *data)
1446 {
1447 g_main_loop_unref (data->loop);
1448 g_main_context_unref (data->context);
1449 g_object_unref (data->server);
1450 g_list_free_full (data->connections, g_object_unref);
1451 g_free (data);
1452 }
1453
1454 static void
1455 dmp_on_method_call (GDBusConnection *connection,
1456 const gchar *sender,
1457 const gchar *object_path,
1458 const gchar *interface_name,
1459 const gchar *method_name,
1460 GVariant *parameters,
1461 GDBusMethodInvocation *invocation,
1462 gpointer user_data)
1463 {
1464 //DmpData *data = user_data;
1465 gint32 first;
1466 gint32 second;
1467 g_variant_get (parameters,
1468 "(ii)",
1469 &first,
1470 &second);
1471 g_dbus_method_invocation_return_value (invocation,
1472 g_variant_new ("(i)", first + second));
1473 }
1474
1475 static const GDBusInterfaceVTable dmp_interface_vtable =
1476 {
1477 dmp_on_method_call,
1478 NULL, /* get_property */
1479 NULL, /* set_property */
1480 { 0 }
1481 };
1482
1483
1484 /* Runs in thread we created GDBusServer in (since we didn't pass G_DBUS_SERVER_FLAGS_RUN_IN_THREAD) */
1485 static gboolean
1486 dmp_on_new_connection (GDBusServer *server,
1487 GDBusConnection *connection,
1488 gpointer user_data)
1489 {
1490 DmpData *data = user_data;
1491 GDBusNodeInfo *node;
1492 GError *error;
1493
1494 /* accept the connection */
1495 data->connections = g_list_prepend (data->connections, g_object_ref (connection));
1496
1497 error = NULL;
1498 node = g_dbus_node_info_new_for_xml ("<node>"
1499 " <interface name='org.gtk.GDBus.DmpInterface'>"
1500 " <method name='AddPair'>"
1501 " <arg type='i' name='first' direction='in'/>"
1502 " <arg type='i' name='second' direction='in'/>"
1503 " <arg type='i' name='sum' direction='out'/>"
1504 " </method>"
1505 " </interface>"
1506 "</node>",
1507 &error);
1508 g_assert_no_error (error);
1509
1510 /* sleep 100ms before exporting an object - this is to test that
1511 * G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING really works
1512 * (GDBusServer uses this feature).
1513 */
1514 g_usleep (100 * 1000);
1515
1516 /* export an object */
1517 error = NULL;
1518 g_dbus_connection_register_object (connection,
1519 "/dmp/test",
1520 node->interfaces[0],
1521 &dmp_interface_vtable,
1522 data,
1523 NULL,
1524 &error);
1525 g_dbus_node_info_unref (node);
1526
1527 return TRUE;
1528 }
1529
1530 static gpointer
1531 dmp_thread_func (gpointer user_data)
1532 {
1533 DmpData *data = user_data;
1534 GError *error;
1535 gchar *guid;
1536
1537 data->context = g_main_context_new ();
1538 g_main_context_push_thread_default (data->context);
1539
1540 error = NULL;
1541 guid = g_dbus_generate_guid ();
1542 data->server = g_dbus_server_new_sync (tmp_address,
1543 G_DBUS_SERVER_FLAGS_NONE,
1544 guid,
1545 NULL, /* GDBusAuthObserver */
1546 NULL, /* GCancellable */
1547 &error);
1548 g_assert_no_error (error);
1549 g_signal_connect (data->server,
1550 "new-connection",
1551 G_CALLBACK (dmp_on_new_connection),
1552 data);
1553
1554 g_dbus_server_start (data->server);
1555
1556 data->loop = g_main_loop_new (data->context, FALSE);
1557 g_main_loop_run (data->loop);
1558
1559 g_dbus_server_stop (data->server);
1560 g_main_context_pop_thread_default (data->context);
1561
1562 g_free (guid);
1563 return NULL;
1564 }
1565
1566 static void
1567 delayed_message_processing (void)
1568 {
1569 GError *error;
1570 DmpData *data;
1571 GThread *service_thread;
1572 guint n;
1573
1574 test_guid = g_dbus_generate_guid ();
1575 loop = g_main_loop_new (NULL, FALSE);
1576
1577 setup_test_address ();
1578
1579 data = g_new0 (DmpData, 1);
1580
1581 service_thread = g_thread_new ("dmp",
1582 dmp_thread_func,
1583 data);
1584 while (data->server == NULL || !g_dbus_server_is_active (data->server))
1585 g_thread_yield ();
1586
1587 for (n = 0; n < 5; n++)
1588 {
1589 GDBusConnection *c;
1590 GVariant *res;
1591 gint32 val;
1592
1593 error = NULL;
1594 c = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (data->server),
1595 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1596 NULL, /* GDBusAuthObserver */
1597 NULL, /* GCancellable */
1598 &error);
1599 g_assert_no_error (error);
1600
1601 error = NULL;
1602 res = g_dbus_connection_call_sync (c,
1603 NULL, /* bus name */
1604 "/dmp/test",
1605 "org.gtk.GDBus.DmpInterface",
1606 "AddPair",
1607 g_variant_new ("(ii)", 2, n),
1608 G_VARIANT_TYPE ("(i)"),
1609 G_DBUS_CALL_FLAGS_NONE,
1610 -1, /* timeout_msec */
1611 NULL, /* GCancellable */
1612 &error);
1613 g_assert_no_error (error);
1614 g_variant_get (res, "(i)", &val);
1615 g_assert_cmpint (val, ==, 2 + n);
1616 g_variant_unref (res);
1617 g_object_unref (c);
1618 }
1619
1620 g_main_loop_quit (data->loop);
1621 g_thread_join (service_thread);
1622 dmp_data_free (data);
1623 teardown_test_address ();
1624
1625 g_main_loop_unref (loop);
1626 g_free (test_guid);
1627 }
1628
1629 /* ---------------------------------------------------------------------------------------------------- */
1630
1631 static gboolean
1632 nonce_tcp_on_authorize_authenticated_peer (GDBusAuthObserver *observer,
1633 GIOStream *stream,
1634 GCredentials *credentials,
1635 gpointer user_data)
1636 {
1637 PeerData *data = user_data;
1638 gboolean authorized;
1639
1640 data->num_connection_attempts++;
1641
1642 authorized = TRUE;
1643 if (!data->accept_connection)
1644 {
1645 authorized = FALSE;
1646 g_main_loop_quit (loop);
1647 }
1648
1649 return authorized;
1650 }
1651
1652 /* Runs in thread we created GDBusServer in (since we didn't pass G_DBUS_SERVER_FLAGS_RUN_IN_THREAD) */
1653 static gboolean
1654 nonce_tcp_on_new_connection (GDBusServer *server,
1655 GDBusConnection *connection,
1656 gpointer user_data)
1657 {
1658 PeerData *data = user_data;
1659
1660 g_ptr_array_add (data->current_connections, g_object_ref (connection));
1661
1662 g_main_loop_quit (loop);
1663
1664 return TRUE;
1665 }
1666
1667 static gpointer
1668 nonce_tcp_service_thread_func (gpointer user_data)
1669 {
1670 PeerData *data = user_data;
1671 GMainContext *service_context;
1672 GDBusAuthObserver *observer;
1673 GError *error;
1674
1675 service_context = g_main_context_new ();
1676 g_main_context_push_thread_default (service_context);
1677
1678 error = NULL;
1679 observer = g_dbus_auth_observer_new ();
1680 server = g_dbus_server_new_sync ("nonce-tcp:host=127.0.0.1",
1681 G_DBUS_SERVER_FLAGS_NONE,
1682 test_guid,
1683 observer,
1684 NULL, /* cancellable */
1685 &error);
1686 g_assert_no_error (error);
1687
1688 g_signal_connect (server,
1689 "new-connection",
1690 G_CALLBACK (nonce_tcp_on_new_connection),
1691 data);
1692 g_signal_connect (observer,
1693 "authorize-authenticated-peer",
1694 G_CALLBACK (nonce_tcp_on_authorize_authenticated_peer),
1695 data);
1696 g_object_unref (observer);
1697
1698 g_dbus_server_start (server);
1699
1700 run_service_loop (service_context);
1701
1702 g_main_context_pop_thread_default (service_context);
1703
1704 teardown_service_loop ();
1705 g_main_context_unref (service_context);
1706
1707 /* test code specifically unrefs the server - see below */
1708 g_assert (server == NULL);
1709
1710 return NULL;
1711 }
1712
1713 static void
1714 test_nonce_tcp (void)
1715 {
1716 PeerData data;
1717 GError *error;
1718 GThread *service_thread;
1719 GDBusConnection *c;
1720 gchar *s;
1721 gchar *nonce_file;
1722 gboolean res;
1723 const gchar *address;
1724 int fd;
1725
1726 test_guid = g_dbus_generate_guid ();
1727 loop = g_main_loop_new (NULL, FALSE);
1728
1729 memset (&data, '\0', sizeof (PeerData));
1730 data.current_connections = g_ptr_array_new_with_free_func (g_object_unref);
1731
1732 error = NULL;
1733 server = NULL;
1734 service_thread = g_thread_new ("nonce-tcp-service",
1735 nonce_tcp_service_thread_func,
1736 &data);
1737 await_service_loop ();
1738 g_assert (server != NULL);
1739
1740 /* bring up a connection and accept it */
1741 data.accept_connection = TRUE;
1742 error = NULL;
1743 c = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (server),
1744 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1745 NULL, /* GDBusAuthObserver */
1746 NULL, /* cancellable */
1747 &error);
1748 g_assert_no_error (error);
1749 g_assert (c != NULL);
1750 while (data.current_connections->len < 1)
1751 g_thread_yield ();
1752 g_assert_cmpint (data.current_connections->len, ==, 1);
1753 g_assert_cmpint (data.num_connection_attempts, ==, 1);
1754 g_assert (g_dbus_connection_get_unique_name (c) == NULL);
1755 g_assert_cmpstr (g_dbus_connection_get_guid (c), ==, test_guid);
1756 g_object_unref (c);
1757
1758 /* now, try to subvert the nonce file (this assumes noncefile is the last key/value pair)
1759 */
1760
1761 address = g_dbus_server_get_client_address (server);
1762
1763 s = strstr (address, "noncefile=");
1764 g_assert (s != NULL);
1765 s += sizeof "noncefile=" - 1;
1766 nonce_file = g_uri_unescape_string (s, NULL); /* URI-unescaping should be good enough */
1767
1768 /* First try invalid data in the nonce file - this will actually
1769 * make the client send this and the server will reject it. The way
1770 * it works is that if the nonce doesn't match, the server will
1771 * simply close the connection. So, from the client point of view,
1772 * we can see a variety of errors.
1773 */
1774 error = NULL;
1775 res = g_file_set_contents (nonce_file,
1776 "0123456789012345",
1777 -1,
1778 &error);
1779 g_assert_no_error (error);
1780 g_assert (res);
1781 c = g_dbus_connection_new_for_address_sync (address,
1782 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1783 NULL, /* GDBusAuthObserver */
1784 NULL, /* cancellable */
1785 &error);
1786 _g_assert_error_domain (error, G_IO_ERROR);
1787 g_error_free (error);
1788 g_assert (c == NULL);
1789
1790 /* Then try with a nonce-file of incorrect length - this will make
1791 * the client complain - we won't even try connecting to the server
1792 * for this
1793 */
1794 error = NULL;
1795 res = g_file_set_contents (nonce_file,
1796 "0123456789012345_",
1797 -1,
1798 &error);
1799 g_assert_no_error (error);
1800 g_assert (res);
1801 c = g_dbus_connection_new_for_address_sync (address,
1802 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1803 NULL, /* GDBusAuthObserver */
1804 NULL, /* cancellable */
1805 &error);
1806 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1807 g_error_free (error);
1808 g_assert (c == NULL);
1809
1810 /* Finally try with no nonce-file at all */
1811 g_assert_cmpint (g_unlink (nonce_file), ==, 0);
1812 error = NULL;
1813 c = g_dbus_connection_new_for_address_sync (address,
1814 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1815 NULL, /* GDBusAuthObserver */
1816 NULL, /* cancellable */
1817 &error);
1818 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1819 g_error_free (error);
1820 g_assert (c == NULL);
1821
1822 /* Recreate the nonce-file so we can ensure the server deletes it when stopped. */
1823 fd = g_creat (nonce_file, 0600);
1824 g_assert_cmpint (fd, !=, -1);
1825 g_close (fd, NULL);
1826
1827 g_dbus_server_stop (server);
1828 g_object_unref (server);
1829 server = NULL;
1830
1831 g_assert_false (g_file_test (nonce_file, G_FILE_TEST_EXISTS));
1832 g_free (nonce_file);
1833
1834 g_main_loop_quit (service_loop);
1835 g_thread_join (service_thread);
1836
1837 g_ptr_array_unref (data.current_connections);
1838
1839 g_main_loop_unref (loop);
1840 g_free (test_guid);
1841 }
1842
1843 static void
1844 test_credentials (void)
1845 {
1846 GCredentials *c1, *c2;
1847 GError *error;
1848 gchar *desc;
1849 gboolean same;
1850
1851 c1 = g_credentials_new ();
1852 c2 = g_credentials_new ();
1853
1854 error = NULL;
1855 #ifdef G_OS_UNIX
1856 if (g_credentials_set_unix_user (c2, getuid (), &error))
1857 g_assert_no_error (error);
1858 #endif
1859
1860 same = g_credentials_is_same_user (c1, c2, &error);
1861 #ifdef G_OS_UNIX
1862 g_assert (same);
1863 g_assert_no_error (error);
1864 #else
1865 g_assert (!same);
1866 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
1867 g_clear_error (&error);
1868 #endif
1869
1870 desc = g_credentials_to_string (c1);
1871 g_assert (desc != NULL);
1872 g_free (desc);
1873
1874 g_object_unref (c1);
1875 g_object_unref (c2);
1876 }
1877
1878 /* ---------------------------------------------------------------------------------------------------- */
1879
1880 static gboolean
1881 tcp_anonymous_on_new_connection (GDBusServer *server,
1882 GDBusConnection *connection,
1883 gpointer user_data)
1884 {
1885 gboolean *seen_connection = user_data;
1886 *seen_connection = TRUE;
1887 return TRUE;
1888 }
1889
1890 static gpointer
1891 tcp_anonymous_service_thread_func (gpointer user_data)
1892 {
1893 gboolean *seen_connection = user_data;
1894 GMainContext *service_context;
1895 GError *error;
1896
1897 service_context = g_main_context_new ();
1898 g_main_context_push_thread_default (service_context);
1899
1900 error = NULL;
1901 server = g_dbus_server_new_sync ("tcp:host=127.0.0.1",
1902 G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS,
1903 test_guid,
1904 NULL, /* GDBusObserver* */
1905 NULL, /* GCancellable* */
1906 &error);
1907 g_assert_no_error (error);
1908
1909 g_signal_connect (server,
1910 "new-connection",
1911 G_CALLBACK (tcp_anonymous_on_new_connection),
1912 seen_connection);
1913
1914 g_dbus_server_start (server);
1915
1916 run_service_loop (service_context);
1917
1918 g_main_context_pop_thread_default (service_context);
1919
1920 teardown_service_loop ();
1921 g_main_context_unref (service_context);
1922
1923 return NULL;
1924 }
1925
1926 static void
1927 test_tcp_anonymous (void)
1928 {
1929 gboolean seen_connection;
1930 GThread *service_thread;
1931 GDBusConnection *connection;
1932 GError *error;
1933
1934 test_guid = g_dbus_generate_guid ();
1935 loop = g_main_loop_new (NULL, FALSE);
1936
1937 seen_connection = FALSE;
1938 service_thread = g_thread_new ("tcp-anon-service",
1939 tcp_anonymous_service_thread_func,
1940 &seen_connection);
1941 await_service_loop ();
1942 g_assert (server != NULL);
1943
1944 error = NULL;
1945 connection = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (server),
1946 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1947 NULL, /* GDBusAuthObserver* */
1948 NULL, /* GCancellable */
1949 &error);
1950 g_assert_no_error (error);
1951 g_assert (connection != NULL);
1952
1953 while (!seen_connection)
1954 g_thread_yield ();
1955
1956 g_object_unref (connection);
1957
1958 g_main_loop_quit (service_loop);
1959 g_dbus_server_stop (server);
1960 g_object_unref (server);
1961 server = NULL;
1962
1963 g_thread_join (service_thread);
1964
1965 g_main_loop_unref (loop);
1966 g_free (test_guid);
1967 }
1968
1969 /* ---------------------------------------------------------------------------------------------------- */
1970
1971 static GDBusServer *codegen_server = NULL;
1972
1973 static gboolean
1974 codegen_on_animal_poke (ExampleAnimal *animal,
1975 GDBusMethodInvocation *invocation,
1976 gboolean make_sad,
1977 gboolean make_happy,
1978 gpointer user_data)
1979 {
1980 if ((make_sad && make_happy) || (!make_sad && !make_happy))
1981 {
1982 g_main_loop_quit (service_loop);
1983
1984 g_dbus_method_invocation_return_dbus_error (invocation,
1985 "org.gtk.GDBus.Examples.ObjectManager.Error.Failed",
1986 "Exactly one of make_sad or make_happy must be TRUE");
1987 goto out;
1988 }
1989
1990 if (make_sad)
1991 {
1992 if (g_strcmp0 (example_animal_get_mood (animal), "Sad") == 0)
1993 {
1994 g_dbus_method_invocation_return_dbus_error (invocation,
1995 "org.gtk.GDBus.Examples.ObjectManager.Error.SadAnimalIsSad",
1996 "Sad animal is already sad");
1997 goto out;
1998 }
1999
2000 example_animal_set_mood (animal, "Sad");
2001 example_animal_complete_poke (animal, invocation);
2002 goto out;
2003 }
2004
2005 if (make_happy)
2006 {
2007 if (g_strcmp0 (example_animal_get_mood (animal), "Happy") == 0)
2008 {
2009 g_dbus_method_invocation_return_dbus_error (invocation,
2010 "org.gtk.GDBus.Examples.ObjectManager.Error.HappyAnimalIsHappy",
2011 "Happy animal is already happy");
2012 goto out;
2013 }
2014
2015 example_animal_set_mood (animal, "Happy");
2016 example_animal_complete_poke (animal, invocation);
2017 goto out;
2018 }
2019
2020 g_assert_not_reached ();
2021
2022 out:
2023 return G_DBUS_METHOD_INVOCATION_HANDLED;
2024 }
2025
2026 /* Runs in thread we created GDBusServer in (since we didn't pass G_DBUS_SERVER_FLAGS_RUN_IN_THREAD) */
2027 static gboolean
2028 codegen_on_new_connection (GDBusServer *server,
2029 GDBusConnection *connection,
2030 gpointer user_data)
2031 {
2032 ExampleAnimal *animal = user_data;
2033 GError *error = NULL;
2034
2035 /* g_printerr ("Client connected.\n" */
2036 /* "Negotiated capabilities: unix-fd-passing=%d\n", */
2037 /* g_dbus_connection_get_capabilities (connection) & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING); */
2038
2039 g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (animal), connection,
2040 "/Example/Animals/000", &error);
2041 g_assert_no_error (error);
2042
2043 return TRUE;
2044 }
2045
2046 static gpointer
2047 codegen_service_thread_func (gpointer user_data)
2048 {
2049 GMainContext *service_context;
2050 ExampleAnimal *animal;
2051 GError *error = NULL;
2052
2053 service_context = g_main_context_new ();
2054 g_main_context_push_thread_default (service_context);
2055
2056 /* Create the animal in the right thread context */
2057 animal = example_animal_skeleton_new ();
2058
2059 /* Handle Poke() D-Bus method invocations on the .Animal interface */
2060 g_signal_connect (animal, "handle-poke",
2061 G_CALLBACK (codegen_on_animal_poke),
2062 NULL); /* user_data */
2063
2064 codegen_server = g_dbus_server_new_sync (tmp_address,
2065 G_DBUS_SERVER_FLAGS_NONE,
2066 test_guid,
2067 NULL, /* observer */
2068 NULL, /* cancellable */
2069 &error);
2070 g_assert_no_error (error);
2071 g_dbus_server_start (codegen_server);
2072
2073 g_signal_connect (codegen_server, "new-connection",
2074 G_CALLBACK (codegen_on_new_connection),
2075 animal);
2076
2077 run_service_loop (service_context);
2078
2079 g_object_unref (animal);
2080
2081 g_main_context_pop_thread_default (service_context);
2082
2083 teardown_service_loop ();
2084 g_main_context_unref (service_context);
2085
2086 g_dbus_server_stop (codegen_server);
2087 g_object_unref (codegen_server);
2088 codegen_server = NULL;
2089
2090 return NULL;
2091 }
2092
2093
2094 static gboolean
2095 codegen_quit_mainloop_timeout (gpointer data)
2096 {
2097 g_main_loop_quit (loop);
2098 return G_SOURCE_REMOVE;
2099 }
2100
2101 static void
2102 codegen_test_peer (void)
2103 {
2104 GDBusConnection *connection;
2105 ExampleAnimal *animal1, *animal2;
2106 GThread *service_thread;
2107 GError *error = NULL;
2108 GVariant *value;
2109 const gchar *s;
2110
2111 test_guid = g_dbus_generate_guid ();
2112 loop = g_main_loop_new (NULL, FALSE);
2113
2114 setup_test_address ();
2115
2116 /* bring up a server - we run the server in a different thread to avoid deadlocks */
2117 service_thread = g_thread_new ("codegen_test_peer",
2118 codegen_service_thread_func,
2119 NULL);
2120 await_service_loop ();
2121 g_assert (codegen_server != NULL);
2122
2123 /* Get an animal 1 ... */
2124 connection = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (codegen_server),
2125 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
2126 NULL, /* GDBusAuthObserver */
2127 NULL, /* cancellable */
2128 &error);
2129 g_assert_no_error (error);
2130 g_assert (connection != NULL);
2131
2132 animal1 = example_animal_proxy_new_sync (connection, 0, NULL,
2133 "/Example/Animals/000", NULL, &error);
2134 g_assert_no_error (error);
2135 g_assert (animal1 != NULL);
2136 g_object_unref (connection);
2137
2138 /* Get animal 2 ... */
2139 connection = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (codegen_server),
2140 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
2141 NULL, /* GDBusAuthObserver */
2142 NULL, /* cancellable */
2143 &error);
2144 g_assert_no_error (error);
2145 g_assert (connection != NULL);
2146
2147 animal2 = example_animal_proxy_new_sync (connection, 0, NULL,
2148 "/Example/Animals/000", NULL, &error);
2149 g_assert_no_error (error);
2150 g_assert (animal2 != NULL);
2151 g_object_unref (connection);
2152
2153 /* Make animal sad via animal1 */
2154 example_animal_call_poke_sync (animal1, TRUE, FALSE, NULL, &error);
2155 g_assert_no_error (error);
2156
2157 /* Poke server and make sure animal is updated */
2158 value = g_dbus_proxy_call_sync (G_DBUS_PROXY (animal1),
2159 "org.freedesktop.DBus.Peer.Ping",
2160 NULL, G_DBUS_CALL_FLAGS_NONE, -1,
2161 NULL, &error);
2162 g_assert_no_error (error);
2163 g_assert (value != NULL);
2164 g_variant_unref (value);
2165
2166 /* Give the proxies a chance to refresh in the default main loop */
2167 g_timeout_add (100, codegen_quit_mainloop_timeout, NULL);
2168 g_main_loop_run (loop);
2169
2170 /* Assert animals are sad */
2171 g_assert_cmpstr (example_animal_get_mood (animal1), ==, "Sad");
2172 g_assert_cmpstr (example_animal_get_mood (animal2), ==, "Sad");
2173
2174 /* Make animal happy via animal2 */
2175 example_animal_call_poke_sync (animal2, FALSE, TRUE, NULL, &error);
2176 g_assert_no_error (error);
2177
2178 /* Some random unrelated call, just to get some test coverage */
2179 value = g_dbus_proxy_call_sync (G_DBUS_PROXY (animal2),
2180 "org.freedesktop.DBus.Peer.GetMachineId",
2181 NULL, G_DBUS_CALL_FLAGS_NONE, -1,
2182 NULL, &error);
2183 g_assert_no_error (error);
2184 g_variant_get (value, "(&s)", &s);
2185 g_test_message ("Machine ID: %s", s);
2186 /* It's valid for machine-id inside containers to be empty, so we
2187 * need to test for that possibility
2188 */
2189 g_assert ((s == NULL || *s == '\0') || g_dbus_is_guid (s));
2190 g_variant_unref (value);
2191
2192 /* Poke server and make sure animal is updated */
2193 value = g_dbus_proxy_call_sync (G_DBUS_PROXY (animal2),
2194 "org.freedesktop.DBus.Peer.Ping",
2195 NULL, G_DBUS_CALL_FLAGS_NONE, -1,
2196 NULL, &error);
2197 g_assert_no_error (error);
2198 g_assert (value != NULL);
2199 g_variant_unref (value);
2200
2201 /* Give the proxies a chance to refresh in the default main loop */
2202 g_timeout_add (1000, codegen_quit_mainloop_timeout, NULL);
2203 g_main_loop_run (loop);
2204
2205 /* Assert animals are happy */
2206 g_assert_cmpstr (example_animal_get_mood (animal1), ==, "Happy");
2207 g_assert_cmpstr (example_animal_get_mood (animal2), ==, "Happy");
2208
2209 /* This final call making the animal happy and sad will cause
2210 * the server to quit, when the server quits we dont get property
2211 * change notifications anyway because those are done from an idle handler
2212 */
2213 example_animal_call_poke_sync (animal2, TRUE, TRUE, NULL, &error);
2214 g_clear_error (&error);
2215
2216 g_object_unref (animal1);
2217 g_object_unref (animal2);
2218 g_thread_join (service_thread);
2219
2220 teardown_test_address ();
2221
2222 g_main_loop_unref (loop);
2223 g_free (test_guid);
2224 }
2225
2226 /* ---------------------------------------------------------------------------------------------------- */
2227
2228
2229 int
2230 main (int argc,
2231 char *argv[])
2232 {
2233 gint ret;
2234 GDBusNodeInfo *introspection_data = NULL;
2235
2236 g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
2237
2238 introspection_data = g_dbus_node_info_new_for_xml (test_interface_introspection_xml, NULL);
2239 g_assert (introspection_data != NULL);
2240 test_interface_introspection_data = introspection_data->interfaces[0];
2241
2242 g_test_add_func ("/gdbus/peer-to-peer", test_peer);
2243 g_test_add_func ("/gdbus/peer-to-peer/invalid/server",
2244 test_peer_invalid_server);
2245 g_test_add_func ("/gdbus/peer-to-peer/invalid/conn/stream/async",
2246 test_peer_invalid_conn_stream_async);
2247 g_test_add_func ("/gdbus/peer-to-peer/invalid/conn/stream/sync",
2248 test_peer_invalid_conn_stream_sync);
2249 g_test_add_func ("/gdbus/peer-to-peer/invalid/conn/addr/async",
2250 test_peer_invalid_conn_addr_async);
2251 g_test_add_func ("/gdbus/peer-to-peer/invalid/conn/addr/sync",
2252 test_peer_invalid_conn_addr_sync);
2253 g_test_add_func ("/gdbus/peer-to-peer/signals", test_peer_signals);
2254 g_test_add_func ("/gdbus/delayed-message-processing", delayed_message_processing);
2255 g_test_add_func ("/gdbus/nonce-tcp", test_nonce_tcp);
2256
2257 g_test_add_func ("/gdbus/tcp-anonymous", test_tcp_anonymous);
2258 g_test_add_func ("/gdbus/credentials", test_credentials);
2259 g_test_add_func ("/gdbus/codegen-peer-to-peer", codegen_test_peer);
2260
2261 ret = g_test_run ();
2262
2263 g_dbus_node_info_unref (introspection_data);
2264
2265 return ret;
2266 }