LCOV - code coverage report
Current view: top level - glib/gio/tests - gdbus-peer.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 736 782 94.1 %
Date: 2024-04-23 05:16:05 Functions: 43 44 97.7 %
Branches: 68 102 66.7 %

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

Generated by: LCOV version 1.14