GDBusServer

## GDBusServer GDBusServer — Helper for accepting connections |

## Synopsis

    #include <gio/gio.h>

                        GDBusServer;
    enum                GDBusServerFlags;
    GDBusServer *       g_dbus_server_new_sync              (const gchar *address,
                                                             GDBusServerFlags flags,
                                                             const gchar *guid,
                                                             GDBusAuthObserver *observer,
                                                             GCancellable *cancellable,
                                                             GError **error);
    void                g_dbus_server_start                 (GDBusServer *server);
    void                g_dbus_server_stop                  (GDBusServer *server);
    gboolean            g_dbus_server_is_active             (GDBusServer *server);
    const gchar *       g_dbus_server_get_guid              (GDBusServer *server);
    GDBusServerFlags    g_dbus_server_get_flags             (GDBusServer *server);
    const gchar *       g_dbus_server_get_client_address    (GDBusServer *server);

## Object Hierarchy

      GObject
       +----GDBusServer

      GFlags
       +----GDBusServerFlags

## Implemented Interfaces

GDBusServer implements GInitable.

## Properties

      "active"                   gboolean              : Read
      "address"                  gchar*                : Read / Write / Construct Only
      "authentication-observer"  GDBusAuthObserver*    : Read / Write / Construct Only
      "client-address"           gchar*                : Read
      "flags"                    GDBusServerFlags      : Read / Write / Construct Only
      "guid"                     gchar*                : Read / Write / Construct Only

## Signals

      "new-connection"                                 : Run Last

## Description

GDBusServer is a helper for listening to and accepting D-Bus connections. This can be used to create a new D-Bus server, allowing two peers to use the D-Bus protocol for their own specialized communication. A server instance provided in this way will not perform message routing or implement the org.freedesktop.DBus interface.

To just export an object on a well-known name on a message bus, such as the session or system bus, you should instead use `g_bus_own_name()`.

Example 6. D-Bus peer-to-peer example

    /*

    Usage examples (modulo addresses / credentials).

    UNIX domain socket transport:

     Server:
       $ ./gdbus-example-peer --server --address unix:abstract=myaddr
       Server is listening at: unix:abstract=myaddr
       Client connected.
       Peer credentials: GCredentials:unix-user=500,unix-group=500,unix-process=13378
       Negotiated capabilities: unix-fd-passing=1
       Client said: Hey, it's 1273093080 already!

     Client:
       $ ./gdbus-example-peer --address unix:abstract=myaddr
       Connected.
       Negotiated capabilities: unix-fd-passing=1
       Server said: You said 'Hey, it's 1273093080 already!'. KTHXBYE!

    Nonce-secured TCP transport on the same host:

     Server:
       $ ./gdbus-example-peer --server --address nonce-tcp:
       Server is listening at: nonce-tcp:host=localhost,port=43077,noncefile=/tmp/gdbus-nonce-file-X1ZNCV
       Client connected.
       Peer credentials: (no credentials received)
       Negotiated capabilities: unix-fd-passing=0
       Client said: Hey, it's 1273093206 already!

     Client:
       $ ./gdbus-example-peer -address nonce-tcp:host=localhost,port=43077,noncefile=/tmp/gdbus-nonce-file-X1ZNCV
       Connected.
       Negotiated capabilities: unix-fd-passing=0
       Server said: You said 'Hey, it's 1273093206 already!'. KTHXBYE!

    TCP transport on two different hosts with a shared home directory:

     Server:
       host1 $ ./gdbus-example-peer --server --address tcp:host=0.0.0.0
       Server is listening at: tcp:host=0.0.0.0,port=46314
       Client connected.
       Peer credentials: (no credentials received)
       Negotiated capabilities: unix-fd-passing=0
       Client said: Hey, it's 1273093337 already!

     Client:
       host2 $ ./gdbus-example-peer -a tcp:host=host1,port=46314
       Connected.
       Negotiated capabilities: unix-fd-passing=0
       Server said: You said 'Hey, it's 1273093337 already!'. KTHXBYE!

    TCP transport on two different hosts without authentication:

     Server:
       host1 $ ./gdbus-example-peer --server --address tcp:host=0.0.0.0 --allow-anonymous
       Server is listening at: tcp:host=0.0.0.0,port=59556
       Client connected.
       Peer credentials: (no credentials received)
       Negotiated capabilities: unix-fd-passing=0
       Client said: Hey, it's 1273093652 already!

     Client:
       host2 $ ./gdbus-example-peer -a tcp:host=host1,port=59556
       Connected.
       Negotiated capabilities: unix-fd-passing=0
       Server said: You said 'Hey, it's 1273093652 already!'. KTHXBYE!

     */

    #include <gio/gio.h>
    #include <stdlib.h>

    /* ---------------------------------------------------------------------------------------------------- */

    static GDBusNodeInfo *introspection_data = NULL;

    /* Introspection data for the service we are exporting */
    static const gchar introspection_xml[] =
      "<node>"
      "  <interface name='org.gtk.GDBus.TestPeerInterface'>"
      "    <method name='HelloWorld'>"
      "      <arg type='s' name='greeting' direction='in'/>"
      "      <arg type='s' name='response' direction='out'/>"
      "    </method>"
      "  </interface>"
      "</node>";

    /* ---------------------------------------------------------------------------------------------------- */

    static void
    handle_method_call (GDBusConnection       *connection,
                        const gchar           *sender,
                        const gchar           *object_path,
                        const gchar           *interface_name,
                        const gchar           *method_name,
                        GVariant              *parameters,
                        GDBusMethodInvocation *invocation,
                        gpointer               user_data)
    {
      if (g_strcmp0 (method_name, "HelloWorld") == 0)
        {
          const gchar *greeting;
          gchar *response;

          g_variant_get (parameters, "(&s)", &greeting);
          response = g_strdup_printf ("You said '%s'. KTHXBYE!", greeting);
          g_dbus_method_invocation_return_value (invocation,
                                                 g_variant_new ("(s)", response));
          g_free (response);
          g_print ("Client said: %s\n", greeting);
        }
    }

    static const GDBusInterfaceVTable interface_vtable =
    {
      handle_method_call,
      NULL,
      NULL,
    };

    /* ---------------------------------------------------------------------------------------------------- */

    static gboolean
    on_new_connection (GDBusServer *server,
                       GDBusConnection *connection,
                       gpointer user_data)
    {
      guint registration_id;
      GCredentials *credentials;
      gchar *s;

      credentials = g_dbus_connection_get_peer_credentials (connection);
      if (credentials == NULL)
        s = g_strdup ("(no credentials received)");
      else
        s = g_credentials_to_string (credentials);

      g_print ("Client connected.\n"
               "Peer credentials: %s\n"
               "Negotiated capabilities: unix-fd-passing=%d\n",
               s,
               g_dbus_connection_get_capabilities (connection) & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING);

      g_object_ref (connection);
      registration_id = g_dbus_connection_register_object (connection,
                                                           "/org/gtk/GDBus/TestObject",
                                                           introspection_data->interfaces[0],
                                                           &interface_vtable,
                                                           NULL,  /* user_data */
                                                           NULL,  /* user_data_free_func */
                                                           NULL); /* GError** */
      g_assert (registration_id > 0);

      return TRUE;
    }

    /* ---------------------------------------------------------------------------------------------------- */

    int
    main (int argc, char *argv[])
    {
      gint ret;
      gboolean opt_server;
      gchar *opt_address;
      GOptionContext *opt_context;
      gboolean opt_allow_anonymous;
      GError *error;
      GOptionEntry opt_entries[] =
        {
          { "server", 's', 0, G_OPTION_ARG_NONE, &opt_server, "Start a server instead of a client", NULL },
          { "address", 'a', 0, G_OPTION_ARG_STRING, &opt_address, "D-Bus address to use", NULL },
          { "allow-anonymous", 'n', 0, G_OPTION_ARG_NONE, &opt_allow_anonymous, "Allow anonymous authentication", NULL },
          { NULL}
        };

      ret = 1;

      g_type_init ();

      opt_address = NULL;
      opt_server = FALSE;
      opt_allow_anonymous = FALSE;

      opt_context = g_option_context_new ("peer-to-peer example");
      error = NULL;
      g_option_context_add_main_entries (opt_context, opt_entries, NULL);
      if (!g_option_context_parse (opt_context, &argc, &argv, &error))
        {
          g_printerr ("Error parsing options: %s\n", error->message);
          g_error_free (error);
          goto out;
        }
      if (opt_address == NULL)
        {
          g_printerr ("Incorrect usage, try --help.\n");
          goto out;
        }
      if (!opt_server && opt_allow_anonymous)
        {
          g_printerr ("The --allow-anonymous option only makes sense when used with --server.\n");
          goto out;
        }

      /* We are lazy here - we don't want to manually provide
       * the introspection data structures - so we just build
       * them from XML.
       */
      introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
      g_assert (introspection_data != NULL);

      if (opt_server)
        {
          GDBusServer *server;
          gchar *guid;
          GMainLoop *loop;
          GDBusServerFlags server_flags;

          guid = g_dbus_generate_guid ();

          server_flags = G_DBUS_SERVER_FLAGS_NONE;
          if (opt_allow_anonymous)
            server_flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS;

          error = NULL;
          server = g_dbus_server_new_sync (opt_address,
                                           server_flags,
                                           guid,
                                           NULL, /* GDBusAuthObserver */
                                           NULL, /* GCancellable */
                                           &error);
          g_dbus_server_start (server);
          g_free (guid);

          if (server == NULL)
            {
              g_printerr ("Error creating server at address %s: %s\n", opt_address, error->message);
              g_error_free (error);
              goto out;
            }
          g_print ("Server is listening at: %s\n", g_dbus_server_get_client_address (server));
          g_signal_connect (server,
                            "new-connection",
                            G_CALLBACK (on_new_connection),
                            NULL);

          loop = g_main_loop_new (NULL, FALSE);
          g_main_loop_run (loop);

          g_object_unref (server);
          g_main_loop_unref (loop);
        }
      else
        {
          GDBusConnection *connection;
          const gchar *greeting_response;
          GVariant *value;
          gchar *greeting;

          error = NULL;
          connection = g_dbus_connection_new_for_address_sync (opt_address,
                                                               G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
                                                               NULL, /* GDBusAuthObserver */
                                                               NULL, /* GCancellable */
                                                               &error);
          if (connection == NULL)
            {
              g_printerr ("Error connecting to D-Bus address %s: %s\n", opt_address, error->message);
              g_error_free (error);
              goto out;
            }

          g_print ("Connected.\n"
                   "Negotiated capabilities: unix-fd-passing=%d\n",
                   g_dbus_connection_get_capabilities (connection) & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING);

          greeting = g_strdup_printf ("Hey, it's %" G_GUINT64_FORMAT " already!", (guint64) time (NULL));
          value = g_dbus_connection_call_sync (connection,
                                               NULL, /* bus_name */
                                               "/org/gtk/GDBus/TestObject",
                                               "org.gtk.GDBus.TestPeerInterface",
                                               "HelloWorld",
                                               g_variant_new ("(s)", greeting),
                                               G_VARIANT_TYPE ("(s)"),
                                               G_DBUS_CALL_FLAGS_NONE,
                                               -1,
                                               NULL,
                                               &error);
          if (value == NULL)
            {
              g_printerr ("Error invoking HelloWorld(): %s\n", error->message);
              g_error_free (error);
              goto out;
            }
          g_variant_get (value, "(&s)", &greeting_response);
          g_print ("Server said: %s\n", greeting_response);
          g_variant_unref (value);

          g_object_unref (connection);
        }
      g_dbus_node_info_unref (introspection_data);

      ret = 0;

     out:
      return ret;
    }

## Details

### GDBusServer

    typedef struct _GDBusServer GDBusServer;

The GDBusServer structure contains only private data and should only be accessed using the provided API.

Since 2.26

### enum GDBusServerFlags

    typedef enum {
      G_DBUS_SERVER_FLAGS_NONE = 0,
      G_DBUS_SERVER_FLAGS_RUN_IN_THREAD = (1<<0),
      G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS = (1<<1)
    } GDBusServerFlags;

Flags used when creating a GDBusServer.

`G_DBUS_SERVER_FLAGS_NONE` | No flags set.
`G_DBUS_SERVER_FLAGS_RUN_IN_THREAD` | All "new-connection" signals will run in separated dedicated threads (see signal for details).
`G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS` | Allow the anonymous authentication method.

Since 2.26

### g_dbus_server_new_sync ()

    GDBusServer *       g_dbus_server_new_sync              (const gchar *address,
                                                             GDBusServerFlags flags,
                                                             const gchar *guid,
                                                             GDBusAuthObserver *observer,
                                                             GCancellable *cancellable,
                                                             GError **error);

Creates a new D-Bus server that listens on the first address in `address` that works.

Once constructed, you can use `g_dbus_server_get_client_address()` to get a D-Bus address string that clients can use to connect.

Connect to the "new-connection" signal to handle incoming connections.

The returned GDBusServer isn't active - you have to start it with `g_dbus_server_start()`.

See Example 6, “D-Bus peer-to-peer example” for how GDBusServer can be used.

This is a synchronous failable constructor. See `g_dbus_server_new()` for the asynchronous version.

`address` : | A D-Bus address.
`flags` : | Flags from the GDBusServerFlags enumeration.
`guid` : | A D-Bus GUID.
`observer` : | A GDBusAuthObserver or `NULL`. [allow-none]
`cancellable` : | A GCancellable or `NULL`. [allow-none]
`error` : | Return location for server or `NULL`.
Returns : | A GDBusServer or `NULL` if `error` is set. Free with `g_object_unref()`.

Since 2.26

### g_dbus_server_start ()

    void                g_dbus_server_start                 (GDBusServer *server);

Starts `server`.

`server` : | A GDBusServer.

Since 2.26

### g_dbus_server_stop ()

    void                g_dbus_server_stop                  (GDBusServer *server);

Stops `server`.

`server` : | A GDBusServer.

Since 2.26

### g_dbus_server_is_active ()

    gboolean            g_dbus_server_is_active             (GDBusServer *server);

Gets whether `server` is active.

`server` : | A GDBusServer.
Returns : | `TRUE` if server is active, `FALSE` otherwise.

Since 2.26

### g_dbus_server_get_guid ()

    const gchar *       g_dbus_server_get_guid              (GDBusServer *server);

Gets the GUID for `server`.

`server` : | A GDBusServer.
Returns : | A D-Bus GUID. Do not free this string, it is owned by `server`.

Since 2.26

### g_dbus_server_get_flags ()

    GDBusServerFlags    g_dbus_server_get_flags             (GDBusServer *server);

Gets the flags for `server`.

`server` : | A GDBusServer.
Returns : | A set of flags from the GDBusServerFlags enumeration.

Since 2.26

### g_dbus_server_get_client_address ()

    const gchar *       g_dbus_server_get_client_address    (GDBusServer *server);

Gets a D-Bus address string that can be used by clients to connect to `server`.

`server` : | A GDBusServer.
Returns : | A D-Bus address string. Do not free, the string is owned by `server`.

Since 2.26

## Property Details

### The `"active"` property

      "active"                   gboolean              : Read

Whether the server is currently active.

Default value: FALSE

Since 2.26

### The `"address"` property

      "address"                  gchar*                : Read / Write / Construct Only

The D-Bus address to listen on.

Default value: NULL

Since 2.26

### The `"authentication-observer"` property

      "authentication-observer"  GDBusAuthObserver*    : Read / Write / Construct Only

A GDBusAuthObserver object to assist in the authentication process or `NULL`.

Since 2.26

### The `"client-address"` property

      "client-address"           gchar*                : Read

The D-Bus address that clients can use.

Default value: NULL

Since 2.26

### The `"flags"` property

      "flags"                    GDBusServerFlags      : Read / Write / Construct Only

Flags from the GDBusServerFlags enumeration.

Since 2.26

### The `"guid"` property

      "guid"                     gchar*                : Read / Write / Construct Only

The guid of the server.

Default value: NULL

Since 2.26

## Signal Details

### The `"new-connection"` signal

    gboolean            user_function                      (GDBusServer     *server,
                                                            GDBusConnection *connection,
                                                            gpointer         user_data)       : Run Last

Emitted when a new authenticated connection has been made. Use `g_dbus_connection_get_peer_credentials()` to figure out what identity (if any), was authenticated.

If you want to accept the connection, take a reference to the `connection` object and return `TRUE`. When you are done with the connection call `g_dbus_connection_close()` and give up your reference. Note that the other peer may disconnect at any time - a typical thing to do when accepting a connection is to listen to the "closed" signal.

If "flags" contains `G_DBUS_SERVER_FLAGS_RUN_IN_THREAD` then the signal is emitted in a new thread dedicated to the connection. Otherwise the signal is emitted in the thread-default main loop of the thread that `server` was constructed in.

You are guaranteed that signal handlers for this signal runs before incoming messages on `connection` are processed. This means that it's suitable to call `g_dbus_connection_register_object()` or similar from the signal handler.

`server` : | The GDBusServer emitting the signal.
`connection` : | A GDBusConnection for the new connection.
`user_data` : | user data set when the signal handler was connected.
Returns : | `TRUE` to claim `connection`, `FALSE` to let other handlers run.

Since 2.26