LCOV - code coverage report
Current view: top level - gio/tests - gdbus-peer.c (source / functions) Coverage Total Hit
Test: unnamed Lines: 94.2 % 782 737
Test Date: 2024-11-26 05:23:01 Functions: 97.7 % 44 43
Branches: - 0 0

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

Generated by: LCOV version 2.0-1