(root)/
glib-2.79.0/
gio/
tests/
gdbus-peer.c
       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  }