LCOV - code coverage report
Current view: top level - gio/tests - gdbus-example-server.c (source / functions) Coverage Total Hit
Test: unnamed Lines: 0.0 % 99 0
Test Date: 2024-11-26 05:23:01 Functions: 0.0 % 8 0
Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : #include <gio/gio.h>
       2                 :             : #include <stdlib.h>
       3                 :             : 
       4                 :             : #ifdef G_OS_UNIX
       5                 :             : #include <gio/gunixfdlist.h>
       6                 :             : /* For STDOUT_FILENO */
       7                 :             : #include <unistd.h>
       8                 :             : #endif
       9                 :             : 
      10                 :             : #define DBUS_INTERFACE_PROPERTIES "org.freedesktop.DBus.Properties"
      11                 :             : 
      12                 :             : /* ---------------------------------------------------------------------------------------------------- */
      13                 :             : 
      14                 :             : static GDBusNodeInfo *introspection_data = NULL;
      15                 :             : 
      16                 :             : /* Introspection data for the service we are exporting */
      17                 :             : static const gchar introspection_xml[] =
      18                 :             :   "<node>"
      19                 :             :   "  <interface name='org.gtk.GDBus.TestInterface'>"
      20                 :             :   "    <annotation name='org.gtk.GDBus.Annotation' value='OnInterface'/>"
      21                 :             :   "    <annotation name='org.gtk.GDBus.Annotation' value='AlsoOnInterface'/>"
      22                 :             :   "    <method name='HelloWorld'>"
      23                 :             :   "      <annotation name='org.gtk.GDBus.Annotation' value='OnMethod'/>"
      24                 :             :   "      <arg type='s' name='greeting' direction='in'/>"
      25                 :             :   "      <arg type='s' name='response' direction='out'/>"
      26                 :             :   "    </method>"
      27                 :             :   "    <method name='EmitSignal'>"
      28                 :             :   "      <arg type='d' name='speed_in_mph' direction='in'>"
      29                 :             :   "        <annotation name='org.gtk.GDBus.Annotation' value='OnArg'/>"
      30                 :             :   "      </arg>"
      31                 :             :   "    </method>"
      32                 :             :   "    <method name='GimmeStdout'/>"
      33                 :             :   "    <signal name='VelocityChanged'>"
      34                 :             :   "      <annotation name='org.gtk.GDBus.Annotation' value='Onsignal'/>"
      35                 :             :   "      <arg type='d' name='speed_in_mph'/>"
      36                 :             :   "      <arg type='s' name='speed_as_string'>"
      37                 :             :   "        <annotation name='org.gtk.GDBus.Annotation' value='OnArg_NonFirst'/>"
      38                 :             :   "      </arg>"
      39                 :             :   "    </signal>"
      40                 :             :   "    <property type='s' name='FluxCapicitorName' access='read'>"
      41                 :             :   "      <annotation name='org.gtk.GDBus.Annotation' value='OnProperty'>"
      42                 :             :   "        <annotation name='org.gtk.GDBus.Annotation' value='OnAnnotation_YesThisIsCrazy'/>"
      43                 :             :   "      </annotation>"
      44                 :             :   "    </property>"
      45                 :             :   "    <property type='s' name='Title' access='readwrite'/>"
      46                 :             :   "    <property type='s' name='ReadingAlwaysThrowsError' access='read'/>"
      47                 :             :   "    <property type='s' name='WritingAlwaysThrowsError' access='readwrite'/>"
      48                 :             :   "    <property type='s' name='OnlyWritable' access='write'/>"
      49                 :             :   "    <property type='s' name='Foo' access='read'/>"
      50                 :             :   "    <property type='s' name='Bar' access='read'/>"
      51                 :             :   "  </interface>"
      52                 :             :   "</node>";
      53                 :             : 
      54                 :             : /* ---------------------------------------------------------------------------------------------------- */
      55                 :             : 
      56                 :             : static void
      57                 :           0 : handle_method_call (GDBusConnection       *connection,
      58                 :             :                     const gchar           *sender,
      59                 :             :                     const gchar           *object_path,
      60                 :             :                     const gchar           *interface_name,
      61                 :             :                     const gchar           *method_name,
      62                 :             :                     GVariant              *parameters,
      63                 :             :                     GDBusMethodInvocation *invocation,
      64                 :             :                     gpointer               user_data)
      65                 :             : {
      66                 :           0 :   if (g_strcmp0 (method_name, "HelloWorld") == 0)
      67                 :             :     {
      68                 :             :       const gchar *greeting;
      69                 :             : 
      70                 :           0 :       g_variant_get (parameters, "(&s)", &greeting);
      71                 :             : 
      72                 :           0 :       if (g_strcmp0 (greeting, "Return Unregistered") == 0)
      73                 :             :         {
      74                 :           0 :           g_dbus_method_invocation_return_error (invocation,
      75                 :             :                                                  G_IO_ERROR,
      76                 :             :                                                  G_IO_ERROR_FAILED_HANDLED,
      77                 :             :                                                  "As requested, here's a GError not registered (G_IO_ERROR_FAILED_HANDLED)");
      78                 :             :         }
      79                 :           0 :       else if (g_strcmp0 (greeting, "Return Registered") == 0)
      80                 :             :         {
      81                 :           0 :           g_dbus_method_invocation_return_error (invocation,
      82                 :             :                                                  G_DBUS_ERROR,
      83                 :             :                                                  G_DBUS_ERROR_MATCH_RULE_NOT_FOUND,
      84                 :             :                                                  "As requested, here's a GError that is registered (G_DBUS_ERROR_MATCH_RULE_NOT_FOUND)");
      85                 :             :         }
      86                 :           0 :       else if (g_strcmp0 (greeting, "Return Raw") == 0)
      87                 :             :         {
      88                 :           0 :           g_dbus_method_invocation_return_dbus_error (invocation,
      89                 :             :                                                       "org.gtk.GDBus.SomeErrorName",
      90                 :             :                                                       "As requested, here's a raw D-Bus error");
      91                 :             :         }
      92                 :             :       else
      93                 :             :         {
      94                 :             :           gchar *response;
      95                 :           0 :           response = g_strdup_printf ("You greeted me with '%s'. Thanks!", greeting);
      96                 :           0 :           g_dbus_method_invocation_return_value (invocation,
      97                 :             :                                                  g_variant_new ("(s)", response));
      98                 :           0 :           g_free (response);
      99                 :             :         }
     100                 :             :     }
     101                 :           0 :   else if (g_strcmp0 (method_name, "EmitSignal") == 0)
     102                 :             :     {
     103                 :             :       GError *local_error;
     104                 :             :       gdouble speed_in_mph;
     105                 :             :       gchar *speed_as_string;
     106                 :             : 
     107                 :           0 :       g_variant_get (parameters, "(d)", &speed_in_mph);
     108                 :           0 :       speed_as_string = g_strdup_printf ("%g mph!", speed_in_mph);
     109                 :             : 
     110                 :           0 :       local_error = NULL;
     111                 :           0 :       g_dbus_connection_emit_signal (connection,
     112                 :             :                                      NULL,
     113                 :             :                                      object_path,
     114                 :             :                                      interface_name,
     115                 :             :                                      "VelocityChanged",
     116                 :             :                                      g_variant_new ("(ds)",
     117                 :             :                                                     speed_in_mph,
     118                 :             :                                                     speed_as_string),
     119                 :             :                                      &local_error);
     120                 :           0 :       g_assert_no_error (local_error);
     121                 :           0 :       g_free (speed_as_string);
     122                 :             : 
     123                 :           0 :       g_dbus_method_invocation_return_value (invocation, NULL);
     124                 :             :     }
     125                 :           0 :   else if (g_strcmp0 (method_name, "GimmeStdout") == 0)
     126                 :             :     {
     127                 :             : #ifdef G_OS_UNIX
     128                 :           0 :       if (g_dbus_connection_get_capabilities (connection) & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING)
     129                 :             :         {
     130                 :             :           GDBusMessage *reply;
     131                 :             :           GUnixFDList *fd_list;
     132                 :             :           GError *error;
     133                 :             : 
     134                 :           0 :           fd_list = g_unix_fd_list_new ();
     135                 :           0 :           error = NULL;
     136                 :           0 :           g_unix_fd_list_append (fd_list, STDOUT_FILENO, &error);
     137                 :           0 :           g_assert_no_error (error);
     138                 :             : 
     139                 :           0 :           reply = g_dbus_message_new_method_reply (g_dbus_method_invocation_get_message (invocation));
     140                 :           0 :           g_dbus_message_set_unix_fd_list (reply, fd_list);
     141                 :             : 
     142                 :           0 :           error = NULL;
     143                 :           0 :           g_dbus_connection_send_message (connection,
     144                 :             :                                           reply,
     145                 :             :                                           G_DBUS_SEND_MESSAGE_FLAGS_NONE,
     146                 :             :                                           NULL, /* out_serial */
     147                 :             :                                           &error);
     148                 :           0 :           g_assert_no_error (error);
     149                 :             : 
     150                 :           0 :           g_object_unref (invocation);
     151                 :           0 :           g_object_unref (fd_list);
     152                 :           0 :           g_object_unref (reply);
     153                 :             :         }
     154                 :             :       else
     155                 :             :         {
     156                 :           0 :           g_dbus_method_invocation_return_dbus_error (invocation,
     157                 :             :                                                       "org.gtk.GDBus.Failed",
     158                 :             :                                                       "Your message bus daemon does not support file descriptor passing (need D-Bus >= 1.3.0)");
     159                 :             :         }
     160                 :             : #else
     161                 :             :       g_dbus_method_invocation_return_dbus_error (invocation,
     162                 :             :                                                   "org.gtk.GDBus.NotOnUnix",
     163                 :             :                                                   "Your OS does not support file descriptor passing");
     164                 :             : #endif
     165                 :             :     }
     166                 :           0 : }
     167                 :             : 
     168                 :             : static gchar *_global_title = NULL;
     169                 :             : 
     170                 :             : static gboolean swap_a_and_b = FALSE;
     171                 :             : 
     172                 :             : static GVariant *
     173                 :           0 : handle_get_property (GDBusConnection  *connection,
     174                 :             :                      const gchar      *sender,
     175                 :             :                      const gchar      *object_path,
     176                 :             :                      const gchar      *interface_name,
     177                 :             :                      const gchar      *property_name,
     178                 :             :                      GError          **error,
     179                 :             :                      gpointer          user_data)
     180                 :             : {
     181                 :             :   GVariant *ret;
     182                 :             : 
     183                 :           0 :   ret = NULL;
     184                 :           0 :   if (g_strcmp0 (property_name, "FluxCapicitorName") == 0)
     185                 :             :     {
     186                 :           0 :       ret = g_variant_new_string ("DeLorean");
     187                 :             :     }
     188                 :           0 :   else if (g_strcmp0 (property_name, "Title") == 0)
     189                 :             :     {
     190                 :           0 :       if (_global_title == NULL)
     191                 :           0 :         _global_title = g_strdup ("Back To C!");
     192                 :           0 :       ret = g_variant_new_string (_global_title);
     193                 :             :     }
     194                 :           0 :   else if (g_strcmp0 (property_name, "ReadingAlwaysThrowsError") == 0)
     195                 :             :     {
     196                 :           0 :       g_set_error (error,
     197                 :             :                    G_IO_ERROR,
     198                 :             :                    G_IO_ERROR_FAILED,
     199                 :             :                    "Hello %s. I thought I said reading this property "
     200                 :             :                    "always results in an error. kthxbye",
     201                 :             :                    sender);
     202                 :             :     }
     203                 :           0 :   else if (g_strcmp0 (property_name, "WritingAlwaysThrowsError") == 0)
     204                 :             :     {
     205                 :           0 :       ret = g_variant_new_string ("There's no home like home");
     206                 :             :     }
     207                 :           0 :   else if (g_strcmp0 (property_name, "Foo") == 0)
     208                 :             :     {
     209                 :           0 :       ret = g_variant_new_string (swap_a_and_b ? "Tock" : "Tick");
     210                 :             :     }
     211                 :           0 :   else if (g_strcmp0 (property_name, "Bar") == 0)
     212                 :             :     {
     213                 :           0 :       ret = g_variant_new_string (swap_a_and_b ? "Tick" : "Tock");
     214                 :             :     }
     215                 :             : 
     216                 :           0 :   return ret;
     217                 :             : }
     218                 :             : 
     219                 :             : static gboolean
     220                 :           0 : handle_set_property (GDBusConnection  *connection,
     221                 :             :                      const gchar      *sender,
     222                 :             :                      const gchar      *object_path,
     223                 :             :                      const gchar      *interface_name,
     224                 :             :                      const gchar      *property_name,
     225                 :             :                      GVariant         *value,
     226                 :             :                      GError          **error,
     227                 :             :                      gpointer          user_data)
     228                 :             : {
     229                 :           0 :   if (g_strcmp0 (property_name, "Title") == 0)
     230                 :             :     {
     231                 :           0 :       if (g_strcmp0 (_global_title, g_variant_get_string (value, NULL)) != 0)
     232                 :             :         {
     233                 :             :           GVariantBuilder *builder;
     234                 :             :           GError *local_error;
     235                 :             : 
     236                 :           0 :           g_free (_global_title);
     237                 :           0 :           _global_title = g_variant_dup_string (value, NULL);
     238                 :             : 
     239                 :           0 :           local_error = NULL;
     240                 :           0 :           builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
     241                 :           0 :           g_variant_builder_add (builder,
     242                 :             :                                  "{sv}",
     243                 :             :                                  "Title",
     244                 :             :                                  g_variant_new_string (_global_title));
     245                 :           0 :           g_dbus_connection_emit_signal (connection,
     246                 :             :                                          NULL,
     247                 :             :                                          object_path,
     248                 :             :                                          DBUS_INTERFACE_PROPERTIES,
     249                 :             :                                          "PropertiesChanged",
     250                 :             :                                          g_variant_new ("(sa{sv}as)",
     251                 :             :                                                         interface_name,
     252                 :             :                                                         builder,
     253                 :             :                                                         NULL),
     254                 :             :                                          &local_error);
     255                 :           0 :           g_assert_no_error (local_error);
     256                 :             :         }
     257                 :             :     }
     258                 :           0 :   else if (g_strcmp0 (property_name, "ReadingAlwaysThrowsError") == 0)
     259                 :             :     {
     260                 :             :       /* do nothing - they can't read it after all! */
     261                 :             :     }
     262                 :           0 :   else if (g_strcmp0 (property_name, "WritingAlwaysThrowsError") == 0)
     263                 :             :     {
     264                 :           0 :       g_set_error (error,
     265                 :             :                    G_IO_ERROR,
     266                 :             :                    G_IO_ERROR_FAILED,
     267                 :             :                    "Hello AGAIN %s. I thought I said writing this property "
     268                 :             :                    "always results in an error. kthxbye",
     269                 :             :                    sender);
     270                 :             :     }
     271                 :             : 
     272                 :           0 :   return *error == NULL;
     273                 :             : }
     274                 :             : 
     275                 :             : 
     276                 :             : /* for now */
     277                 :             : static const GDBusInterfaceVTable interface_vtable =
     278                 :             : {
     279                 :             :   handle_method_call,
     280                 :             :   handle_get_property,
     281                 :             :   handle_set_property,
     282                 :             :   { 0 }
     283                 :             : };
     284                 :             : 
     285                 :             : /* ---------------------------------------------------------------------------------------------------- */
     286                 :             : 
     287                 :             : static gboolean
     288                 :           0 : on_timeout_cb (gpointer user_data)
     289                 :             : {
     290                 :           0 :   GDBusConnection *connection = G_DBUS_CONNECTION (user_data);
     291                 :             :   GVariantBuilder *builder;
     292                 :             :   GVariantBuilder *invalidated_builder;
     293                 :             :   GError *error;
     294                 :             : 
     295                 :           0 :   swap_a_and_b = !swap_a_and_b;
     296                 :             : 
     297                 :           0 :   error = NULL;
     298                 :           0 :   builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
     299                 :           0 :   invalidated_builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
     300                 :           0 :   g_variant_builder_add (builder,
     301                 :             :                          "{sv}",
     302                 :             :                          "Foo",
     303                 :           0 :                          g_variant_new_string (swap_a_and_b ? "Tock" : "Tick"));
     304                 :           0 :   g_variant_builder_add (builder,
     305                 :             :                          "{sv}",
     306                 :             :                          "Bar",
     307                 :           0 :                          g_variant_new_string (swap_a_and_b ? "Tick" : "Tock"));
     308                 :           0 :   g_dbus_connection_emit_signal (connection,
     309                 :             :                                  NULL,
     310                 :             :                                  "/org/gtk/GDBus/TestObject",
     311                 :             :                                  DBUS_INTERFACE_PROPERTIES,
     312                 :             :                                  "PropertiesChanged",
     313                 :             :                                  g_variant_new ("(sa{sv}as)",
     314                 :             :                                                 "org.gtk.GDBus.TestInterface",
     315                 :             :                                                 builder,
     316                 :             :                                                 invalidated_builder),
     317                 :             :                                  &error);
     318                 :           0 :   g_assert_no_error (error);
     319                 :             : 
     320                 :             : 
     321                 :           0 :   return G_SOURCE_CONTINUE;
     322                 :             : }
     323                 :             : 
     324                 :             : /* ---------------------------------------------------------------------------------------------------- */
     325                 :             : 
     326                 :             : static void
     327                 :           0 : on_bus_acquired (GDBusConnection *connection,
     328                 :             :                  const gchar     *name,
     329                 :             :                  gpointer         user_data)
     330                 :             : {
     331                 :             :   guint registration_id;
     332                 :             : 
     333                 :           0 :   registration_id = g_dbus_connection_register_object (connection,
     334                 :             :                                                        "/org/gtk/GDBus/TestObject",
     335                 :           0 :                                                        introspection_data->interfaces[0],
     336                 :             :                                                        &interface_vtable,
     337                 :             :                                                        NULL,  /* user_data */
     338                 :             :                                                        NULL,  /* user_data_free_func */
     339                 :             :                                                        NULL); /* GError** */
     340                 :           0 :   g_assert (registration_id > 0);
     341                 :             : 
     342                 :             :   /* swap value of properties Foo and Bar every two seconds */
     343                 :           0 :   g_timeout_add_seconds (2,
     344                 :             :                          on_timeout_cb,
     345                 :             :                          connection);
     346                 :           0 : }
     347                 :             : 
     348                 :             : static void
     349                 :           0 : on_name_acquired (GDBusConnection *connection,
     350                 :             :                   const gchar     *name,
     351                 :             :                   gpointer         user_data)
     352                 :             : {
     353                 :           0 : }
     354                 :             : 
     355                 :             : static void
     356                 :           0 : on_name_lost (GDBusConnection *connection,
     357                 :             :               const gchar     *name,
     358                 :             :               gpointer         user_data)
     359                 :             : {
     360                 :           0 :   exit (1);
     361                 :             : }
     362                 :             : 
     363                 :             : int
     364                 :           0 : main (int argc, char *argv[])
     365                 :             : {
     366                 :             :   guint owner_id;
     367                 :             :   GMainLoop *loop;
     368                 :             : 
     369                 :             :   /* We are lazy here - we don't want to manually provide
     370                 :             :    * the introspection data structures - so we just build
     371                 :             :    * them from XML.
     372                 :             :    */
     373                 :           0 :   introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
     374                 :           0 :   g_assert (introspection_data != NULL);
     375                 :             : 
     376                 :           0 :   owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
     377                 :             :                              "org.gtk.GDBus.TestServer",
     378                 :             :                              G_BUS_NAME_OWNER_FLAGS_NONE,
     379                 :             :                              on_bus_acquired,
     380                 :             :                              on_name_acquired,
     381                 :             :                              on_name_lost,
     382                 :             :                              NULL,
     383                 :             :                              NULL);
     384                 :             : 
     385                 :           0 :   loop = g_main_loop_new (NULL, FALSE);
     386                 :           0 :   g_main_loop_run (loop);
     387                 :             : 
     388                 :           0 :   g_bus_unown_name (owner_id);
     389                 :             : 
     390                 :           0 :   g_dbus_node_info_unref (introspection_data);
     391                 :             : 
     392                 :           0 :   return 0;
     393                 :             : }
        

Generated by: LCOV version 2.0-1