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