LCOV - code coverage report
Current view: top level - glib/gio - gdbusserver.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 296 350 84.6 %
Date: 2024-04-23 05:16:05 Functions: 24 24 100.0 %
Branches: 98 153 64.1 %

           Branch data     Line data    Source code
       1                 :            : /* GDBus - GLib D-Bus Library
       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 <stdlib.h>
      26                 :            : #include <string.h>
      27                 :            : #include <errno.h>
      28                 :            : 
      29                 :            : #include "giotypes.h"
      30                 :            : #include "gioerror.h"
      31                 :            : #include "gdbusaddress.h"
      32                 :            : #include "gdbusutils.h"
      33                 :            : #include "gdbusconnection.h"
      34                 :            : #include "gdbusserver.h"
      35                 :            : #include "gioenumtypes.h"
      36                 :            : #include "gdbusprivate.h"
      37                 :            : #include "gdbusauthobserver.h"
      38                 :            : #include "ginitable.h"
      39                 :            : #include "gsocketservice.h"
      40                 :            : #include "gthreadedsocketservice.h"
      41                 :            : #include "gresolver.h"
      42                 :            : #include "glib/gstdio.h"
      43                 :            : #include "ginetaddress.h"
      44                 :            : #include "ginetsocketaddress.h"
      45                 :            : #include "ginputstream.h"
      46                 :            : #include "giostream.h"
      47                 :            : #include "gmarshal-internal.h"
      48                 :            : 
      49                 :            : #ifdef G_OS_UNIX
      50                 :            : #include <unistd.h>
      51                 :            : #endif
      52                 :            : #ifdef G_OS_WIN32
      53                 :            : #include <io.h>
      54                 :            : #endif
      55                 :            : 
      56                 :            : #include "gunixsocketaddress.h"
      57                 :            : 
      58                 :            : #include "glibintl.h"
      59                 :            : 
      60                 :            : #define G_DBUS_SERVER_FLAGS_ALL \
      61                 :            :   (G_DBUS_SERVER_FLAGS_RUN_IN_THREAD | \
      62                 :            :    G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS | \
      63                 :            :    G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER)
      64                 :            : 
      65                 :            : /**
      66                 :            :  * GDBusServer:
      67                 :            :  *
      68                 :            :  * `GDBusServer` is a helper for listening to and accepting D-Bus
      69                 :            :  * connections. This can be used to create a new D-Bus server, allowing two
      70                 :            :  * peers to use the D-Bus protocol for their own specialized communication.
      71                 :            :  * A server instance provided in this way will not perform message routing or
      72                 :            :  * implement the
      73                 :            :  * [`org.freedesktop.DBus` interface](https://dbus.freedesktop.org/doc/dbus-specification.html#message-bus-messages).
      74                 :            :  *
      75                 :            :  * To just export an object on a well-known name on a message bus, such as the
      76                 :            :  * session or system bus, you should instead use [func@Gio.bus_own_name].
      77                 :            :  *
      78                 :            :  * An example of peer-to-peer communication with GDBus can be found
      79                 :            :  * in [gdbus-example-peer.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gdbus-example-peer.c).
      80                 :            :  *
      81                 :            :  * Note that a minimal `GDBusServer` will accept connections from any
      82                 :            :  * peer. In many use-cases it will be necessary to add a
      83                 :            :  * [class@Gio.DBusAuthObserver] that only accepts connections that have
      84                 :            :  * successfully authenticated as the same user that is running the
      85                 :            :  * `GDBusServer`. Since GLib 2.68 this can be achieved more simply by passing
      86                 :            :  * the `G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER` flag to the
      87                 :            :  * server.
      88                 :            :  *
      89                 :            :  * Since: 2.26
      90                 :            :  */
      91                 :            : struct _GDBusServer
      92                 :            : {
      93                 :            :   /*< private >*/
      94                 :            :   GObject parent_instance;
      95                 :            : 
      96                 :            :   GDBusServerFlags flags;
      97                 :            :   gchar *address;
      98                 :            :   gchar *guid;
      99                 :            : 
     100                 :            :   guchar *nonce;
     101                 :            :   gchar *nonce_file;
     102                 :            : 
     103                 :            :   gchar *client_address;
     104                 :            : 
     105                 :            :   gchar *unix_socket_path;
     106                 :            :   GSocketListener *listener;
     107                 :            :   gboolean is_using_listener;
     108                 :            :   gulong run_signal_handler_id;
     109                 :            : 
     110                 :            :   /* The result of g_main_context_ref_thread_default() when the object
     111                 :            :    * was created (the GObject _init() function) - this is used for delivery
     112                 :            :    * of the :new-connection GObject signal.
     113                 :            :    */
     114                 :            :   GMainContext *main_context_at_construction;
     115                 :            : 
     116                 :            :   gboolean active;
     117                 :            : 
     118                 :            :   GDBusAuthObserver *authentication_observer;
     119                 :            : };
     120                 :            : 
     121                 :            : typedef struct _GDBusServerClass GDBusServerClass;
     122                 :            : 
     123                 :            : /**
     124                 :            :  * GDBusServerClass:
     125                 :            :  * @new_connection: Signal class handler for the #GDBusServer::new-connection signal.
     126                 :            :  *
     127                 :            :  * Class structure for #GDBusServer.
     128                 :            :  *
     129                 :            :  * Since: 2.26
     130                 :            :  */
     131                 :            : struct _GDBusServerClass
     132                 :            : {
     133                 :            :   /*< private >*/
     134                 :            :   GObjectClass parent_class;
     135                 :            : 
     136                 :            :   /*< public >*/
     137                 :            :   /* Signals */
     138                 :            :   gboolean (*new_connection) (GDBusServer      *server,
     139                 :            :                               GDBusConnection  *connection);
     140                 :            : };
     141                 :            : 
     142                 :            : enum
     143                 :            : {
     144                 :            :   PROP_0,
     145                 :            :   PROP_ADDRESS,
     146                 :            :   PROP_CLIENT_ADDRESS,
     147                 :            :   PROP_FLAGS,
     148                 :            :   PROP_GUID,
     149                 :            :   PROP_ACTIVE,
     150                 :            :   PROP_AUTHENTICATION_OBSERVER,
     151                 :            : };
     152                 :            : 
     153                 :            : enum
     154                 :            : {
     155                 :            :   NEW_CONNECTION_SIGNAL,
     156                 :            :   LAST_SIGNAL,
     157                 :            : };
     158                 :            : 
     159                 :            : static guint _signals[LAST_SIGNAL] = {0};
     160                 :            : 
     161                 :            : static void initable_iface_init       (GInitableIface *initable_iface);
     162                 :            : 
     163   [ +  +  +  -  :        703 : G_DEFINE_TYPE_WITH_CODE (GDBusServer, g_dbus_server, G_TYPE_OBJECT,
                   +  + ]
     164                 :            :                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init))
     165                 :            : 
     166                 :            : static void
     167                 :         25 : g_dbus_server_dispose (GObject *object)
     168                 :            : {
     169                 :         25 :   GDBusServer *server = G_DBUS_SERVER (object);
     170                 :            : 
     171         [ -  + ]:         25 :   if (server->active)
     172                 :          0 :     g_dbus_server_stop (server);
     173                 :            : 
     174                 :         25 :   G_OBJECT_CLASS (g_dbus_server_parent_class)->dispose (object);
     175                 :         25 : }
     176                 :            : 
     177                 :            : static void
     178                 :         25 : g_dbus_server_finalize (GObject *object)
     179                 :            : {
     180                 :         25 :   GDBusServer *server = G_DBUS_SERVER (object);
     181                 :            : 
     182                 :         25 :   g_assert (!server->active);
     183                 :            : 
     184         [ +  + ]:         25 :   if (server->authentication_observer != NULL)
     185                 :         19 :     g_object_unref (server->authentication_observer);
     186                 :            : 
     187         [ -  + ]:         25 :   if (server->run_signal_handler_id > 0)
     188                 :          0 :     g_signal_handler_disconnect (server->listener, server->run_signal_handler_id);
     189                 :            : 
     190         [ +  - ]:         25 :   if (server->listener != NULL)
     191                 :         25 :     g_object_unref (server->listener);
     192                 :            : 
     193                 :         25 :   g_free (server->address);
     194                 :         25 :   g_free (server->guid);
     195                 :         25 :   g_free (server->client_address);
     196         [ +  + ]:         25 :   if (server->nonce != NULL)
     197                 :            :     {
     198                 :          1 :       memset (server->nonce, '\0', 16);
     199                 :          1 :       g_free (server->nonce);
     200                 :            :     }
     201                 :            : 
     202                 :         25 :   g_free (server->unix_socket_path);
     203                 :         25 :   g_free (server->nonce_file);
     204                 :            : 
     205                 :         25 :   g_main_context_unref (server->main_context_at_construction);
     206                 :            : 
     207                 :         25 :   G_OBJECT_CLASS (g_dbus_server_parent_class)->finalize (object);
     208                 :         25 : }
     209                 :            : 
     210                 :            : static void
     211                 :         20 : g_dbus_server_get_property (GObject    *object,
     212                 :            :                             guint       prop_id,
     213                 :            :                             GValue     *value,
     214                 :            :                             GParamSpec *pspec)
     215                 :            : {
     216                 :         20 :   GDBusServer *server = G_DBUS_SERVER (object);
     217                 :            : 
     218   [ +  +  +  -  :         20 :   switch (prop_id)
                +  +  - ]
     219                 :            :     {
     220                 :          4 :     case PROP_FLAGS:
     221                 :          4 :       g_value_set_flags (value, server->flags);
     222                 :          4 :       break;
     223                 :            : 
     224                 :          4 :     case PROP_GUID:
     225                 :          4 :       g_value_set_string (value, server->guid);
     226                 :          4 :       break;
     227                 :            : 
     228                 :          4 :     case PROP_ADDRESS:
     229                 :          4 :       g_value_set_string (value, server->address);
     230                 :          4 :       break;
     231                 :            : 
     232                 :          0 :     case PROP_CLIENT_ADDRESS:
     233                 :          0 :       g_value_set_string (value, server->client_address);
     234                 :          0 :       break;
     235                 :            : 
     236                 :          4 :     case PROP_ACTIVE:
     237                 :          4 :       g_value_set_boolean (value, server->active);
     238                 :          4 :       break;
     239                 :            : 
     240                 :          4 :     case PROP_AUTHENTICATION_OBSERVER:
     241                 :          4 :       g_value_set_object (value, server->authentication_observer);
     242                 :          4 :       break;
     243                 :            : 
     244                 :          0 :     default:
     245                 :          0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     246                 :          0 :       break;
     247                 :            :     }
     248                 :         20 : }
     249                 :            : 
     250                 :            : static void
     251                 :        100 : g_dbus_server_set_property (GObject      *object,
     252                 :            :                             guint         prop_id,
     253                 :            :                             const GValue *value,
     254                 :            :                             GParamSpec   *pspec)
     255                 :            : {
     256                 :        100 :   GDBusServer *server = G_DBUS_SERVER (object);
     257                 :            : 
     258   [ +  +  +  +  :        100 :   switch (prop_id)
                      - ]
     259                 :            :     {
     260                 :         25 :     case PROP_FLAGS:
     261                 :         25 :       server->flags = g_value_get_flags (value);
     262                 :         25 :       break;
     263                 :            : 
     264                 :         25 :     case PROP_GUID:
     265                 :         25 :       server->guid = g_value_dup_string (value);
     266                 :         25 :       break;
     267                 :            : 
     268                 :         25 :     case PROP_ADDRESS:
     269                 :         25 :       server->address = g_value_dup_string (value);
     270                 :         25 :       break;
     271                 :            : 
     272                 :         25 :     case PROP_AUTHENTICATION_OBSERVER:
     273                 :         25 :       server->authentication_observer = g_value_dup_object (value);
     274                 :         25 :       break;
     275                 :            : 
     276                 :          0 :     default:
     277                 :          0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     278                 :          0 :       break;
     279                 :            :     }
     280                 :        100 : }
     281                 :            : 
     282                 :            : static void
     283                 :          6 : g_dbus_server_class_init (GDBusServerClass *klass)
     284                 :            : {
     285                 :          6 :   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     286                 :            : 
     287                 :          6 :   gobject_class->dispose      = g_dbus_server_dispose;
     288                 :          6 :   gobject_class->finalize     = g_dbus_server_finalize;
     289                 :          6 :   gobject_class->set_property = g_dbus_server_set_property;
     290                 :          6 :   gobject_class->get_property = g_dbus_server_get_property;
     291                 :            : 
     292                 :            :   /**
     293                 :            :    * GDBusServer:flags:
     294                 :            :    *
     295                 :            :    * Flags from the #GDBusServerFlags enumeration.
     296                 :            :    *
     297                 :            :    * Since: 2.26
     298                 :            :    */
     299                 :          6 :   g_object_class_install_property (gobject_class,
     300                 :            :                                    PROP_FLAGS,
     301                 :            :                                    g_param_spec_flags ("flags", NULL, NULL,
     302                 :            :                                                        G_TYPE_DBUS_SERVER_FLAGS,
     303                 :            :                                                        G_DBUS_SERVER_FLAGS_NONE,
     304                 :            :                                                        G_PARAM_READABLE |
     305                 :            :                                                        G_PARAM_WRITABLE |
     306                 :            :                                                        G_PARAM_CONSTRUCT_ONLY |
     307                 :            :                                                        G_PARAM_STATIC_NAME |
     308                 :            :                                                        G_PARAM_STATIC_BLURB |
     309                 :            :                                                        G_PARAM_STATIC_NICK));
     310                 :            : 
     311                 :            :   /**
     312                 :            :    * GDBusServer:guid:
     313                 :            :    *
     314                 :            :    * The GUID of the server.
     315                 :            :    *
     316                 :            :    * See #GDBusConnection:guid for more details.
     317                 :            :    *
     318                 :            :    * Since: 2.26
     319                 :            :    */
     320                 :          6 :   g_object_class_install_property (gobject_class,
     321                 :            :                                    PROP_GUID,
     322                 :            :                                    g_param_spec_string ("guid", NULL, NULL,
     323                 :            :                                                         NULL,
     324                 :            :                                                         G_PARAM_READABLE |
     325                 :            :                                                         G_PARAM_WRITABLE |
     326                 :            :                                                         G_PARAM_CONSTRUCT_ONLY |
     327                 :            :                                                         G_PARAM_STATIC_NAME |
     328                 :            :                                                         G_PARAM_STATIC_BLURB |
     329                 :            :                                                         G_PARAM_STATIC_NICK));
     330                 :            : 
     331                 :            :   /**
     332                 :            :    * GDBusServer:address:
     333                 :            :    *
     334                 :            :    * The D-Bus address to listen on.
     335                 :            :    *
     336                 :            :    * Since: 2.26
     337                 :            :    */
     338                 :          6 :   g_object_class_install_property (gobject_class,
     339                 :            :                                    PROP_ADDRESS,
     340                 :            :                                    g_param_spec_string ("address", NULL, NULL,
     341                 :            :                                                         NULL,
     342                 :            :                                                         G_PARAM_READABLE |
     343                 :            :                                                         G_PARAM_WRITABLE |
     344                 :            :                                                         G_PARAM_CONSTRUCT_ONLY |
     345                 :            :                                                         G_PARAM_STATIC_NAME |
     346                 :            :                                                         G_PARAM_STATIC_BLURB |
     347                 :            :                                                         G_PARAM_STATIC_NICK));
     348                 :            : 
     349                 :            :   /**
     350                 :            :    * GDBusServer:client-address:
     351                 :            :    *
     352                 :            :    * The D-Bus address that clients can use.
     353                 :            :    *
     354                 :            :    * Since: 2.26
     355                 :            :    */
     356                 :          6 :   g_object_class_install_property (gobject_class,
     357                 :            :                                    PROP_CLIENT_ADDRESS,
     358                 :            :                                    g_param_spec_string ("client-address", NULL, NULL,
     359                 :            :                                                         NULL,
     360                 :            :                                                         G_PARAM_READABLE |
     361                 :            :                                                         G_PARAM_STATIC_NAME |
     362                 :            :                                                         G_PARAM_STATIC_BLURB |
     363                 :            :                                                         G_PARAM_STATIC_NICK));
     364                 :            : 
     365                 :            :   /**
     366                 :            :    * GDBusServer:active:
     367                 :            :    *
     368                 :            :    * Whether the server is currently active.
     369                 :            :    *
     370                 :            :    * Since: 2.26
     371                 :            :    */
     372                 :          6 :   g_object_class_install_property (gobject_class,
     373                 :            :                                    PROP_ACTIVE,
     374                 :            :                                    g_param_spec_boolean ("active", NULL, NULL,
     375                 :            :                                                          FALSE,
     376                 :            :                                                          G_PARAM_READABLE |
     377                 :            :                                                          G_PARAM_STATIC_NAME |
     378                 :            :                                                          G_PARAM_STATIC_BLURB |
     379                 :            :                                                          G_PARAM_STATIC_NICK));
     380                 :            : 
     381                 :            :   /**
     382                 :            :    * GDBusServer:authentication-observer:
     383                 :            :    *
     384                 :            :    * A #GDBusAuthObserver object to assist in the authentication process or %NULL.
     385                 :            :    *
     386                 :            :    * Since: 2.26
     387                 :            :    */
     388                 :          6 :   g_object_class_install_property (gobject_class,
     389                 :            :                                    PROP_AUTHENTICATION_OBSERVER,
     390                 :            :                                    g_param_spec_object ("authentication-observer", NULL, NULL,
     391                 :            :                                                         G_TYPE_DBUS_AUTH_OBSERVER,
     392                 :            :                                                         G_PARAM_READABLE |
     393                 :            :                                                         G_PARAM_WRITABLE |
     394                 :            :                                                         G_PARAM_CONSTRUCT_ONLY |
     395                 :            :                                                         G_PARAM_STATIC_NAME |
     396                 :            :                                                         G_PARAM_STATIC_BLURB |
     397                 :            :                                                         G_PARAM_STATIC_NICK));
     398                 :            : 
     399                 :            :   /**
     400                 :            :    * GDBusServer::new-connection:
     401                 :            :    * @server: The #GDBusServer emitting the signal.
     402                 :            :    * @connection: A #GDBusConnection for the new connection.
     403                 :            :    *
     404                 :            :    * Emitted when a new authenticated connection has been made. Use
     405                 :            :    * g_dbus_connection_get_peer_credentials() to figure out what
     406                 :            :    * identity (if any), was authenticated.
     407                 :            :    *
     408                 :            :    * If you want to accept the connection, take a reference to the
     409                 :            :    * @connection object and return %TRUE. When you are done with the
     410                 :            :    * connection call g_dbus_connection_close() and give up your
     411                 :            :    * reference. Note that the other peer may disconnect at any time -
     412                 :            :    * a typical thing to do when accepting a connection is to listen to
     413                 :            :    * the #GDBusConnection::closed signal.
     414                 :            :    *
     415                 :            :    * If #GDBusServer:flags contains %G_DBUS_SERVER_FLAGS_RUN_IN_THREAD
     416                 :            :    * then the signal is emitted in a new thread dedicated to the
     417                 :            :    * connection. Otherwise the signal is emitted in the
     418                 :            :    * [thread-default main context][g-main-context-push-thread-default]
     419                 :            :    * of the thread that @server was constructed in.
     420                 :            :    *
     421                 :            :    * You are guaranteed that signal handlers for this signal runs
     422                 :            :    * before incoming messages on @connection are processed. This means
     423                 :            :    * that it's suitable to call g_dbus_connection_register_object() or
     424                 :            :    * similar from the signal handler.
     425                 :            :    *
     426                 :            :    * Returns: %TRUE to claim @connection, %FALSE to let other handlers
     427                 :            :    * run.
     428                 :            :    *
     429                 :            :    * Since: 2.26
     430                 :            :    */
     431                 :          6 :   _signals[NEW_CONNECTION_SIGNAL] = g_signal_new (I_("new-connection"),
     432                 :            :                                                   G_TYPE_DBUS_SERVER,
     433                 :            :                                                   G_SIGNAL_RUN_LAST,
     434                 :            :                                                   G_STRUCT_OFFSET (GDBusServerClass, new_connection),
     435                 :            :                                                   g_signal_accumulator_true_handled,
     436                 :            :                                                   NULL, /* accu_data */
     437                 :            :                                                   _g_cclosure_marshal_BOOLEAN__OBJECT,
     438                 :            :                                                   G_TYPE_BOOLEAN,
     439                 :            :                                                   1,
     440                 :            :                                                   G_TYPE_DBUS_CONNECTION);
     441                 :          6 :   g_signal_set_va_marshaller (_signals[NEW_CONNECTION_SIGNAL],
     442                 :            :                               G_TYPE_FROM_CLASS (klass),
     443                 :            :                               _g_cclosure_marshal_BOOLEAN__OBJECTv);
     444                 :          6 : }
     445                 :            : 
     446                 :            : static void
     447                 :         25 : g_dbus_server_init (GDBusServer *server)
     448                 :            : {
     449                 :         25 :   server->main_context_at_construction = g_main_context_ref_thread_default ();
     450                 :         25 : }
     451                 :            : 
     452                 :            : static gboolean
     453                 :            : on_run (GSocketService    *service,
     454                 :            :         GSocketConnection *socket_connection,
     455                 :            :         GObject           *source_object,
     456                 :            :         gpointer           user_data);
     457                 :            : 
     458                 :            : /**
     459                 :            :  * g_dbus_server_new_sync:
     460                 :            :  * @address: A D-Bus address.
     461                 :            :  * @flags: Flags from the #GDBusServerFlags enumeration.
     462                 :            :  * @guid: A D-Bus GUID.
     463                 :            :  * @observer: (nullable): A #GDBusAuthObserver or %NULL.
     464                 :            :  * @cancellable: (nullable): A #GCancellable or %NULL.
     465                 :            :  * @error: Return location for server or %NULL.
     466                 :            :  *
     467                 :            :  * Creates a new D-Bus server that listens on the first address in
     468                 :            :  * @address that works.
     469                 :            :  *
     470                 :            :  * Once constructed, you can use g_dbus_server_get_client_address() to
     471                 :            :  * get a D-Bus address string that clients can use to connect.
     472                 :            :  *
     473                 :            :  * To have control over the available authentication mechanisms and
     474                 :            :  * the users that are authorized to connect, it is strongly recommended
     475                 :            :  * to provide a non-%NULL #GDBusAuthObserver.
     476                 :            :  *
     477                 :            :  * Connect to the #GDBusServer::new-connection signal to handle
     478                 :            :  * incoming connections.
     479                 :            :  *
     480                 :            :  * The returned #GDBusServer isn't active - you have to start it with
     481                 :            :  * g_dbus_server_start().
     482                 :            :  *
     483                 :            :  * #GDBusServer is used in this [example][gdbus-peer-to-peer].
     484                 :            :  *
     485                 :            :  * This is a synchronous failable constructor. There is currently no
     486                 :            :  * asynchronous version.
     487                 :            :  *
     488                 :            :  * Returns: A #GDBusServer or %NULL if @error is set. Free with
     489                 :            :  * g_object_unref().
     490                 :            :  *
     491                 :            :  * Since: 2.26
     492                 :            :  */
     493                 :            : GDBusServer *
     494                 :         25 : g_dbus_server_new_sync (const gchar        *address,
     495                 :            :                         GDBusServerFlags    flags,
     496                 :            :                         const gchar        *guid,
     497                 :            :                         GDBusAuthObserver  *observer,
     498                 :            :                         GCancellable       *cancellable,
     499                 :            :                         GError            **error)
     500                 :            : {
     501                 :            :   GDBusServer *server;
     502                 :            : 
     503                 :         25 :   g_return_val_if_fail (address != NULL, NULL);
     504                 :         25 :   g_return_val_if_fail (g_dbus_is_guid (guid), NULL);
     505                 :         25 :   g_return_val_if_fail ((flags & ~G_DBUS_SERVER_FLAGS_ALL) == 0, NULL);
     506                 :         25 :   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
     507                 :            : 
     508                 :         25 :   server = g_initable_new (G_TYPE_DBUS_SERVER,
     509                 :            :                            cancellable,
     510                 :            :                            error,
     511                 :            :                            "address", address,
     512                 :            :                            "flags", flags,
     513                 :            :                            "guid", guid,
     514                 :            :                            "authentication-observer", observer,
     515                 :            :                            NULL);
     516                 :            : 
     517                 :         25 :   return server;
     518                 :            : }
     519                 :            : 
     520                 :            : /**
     521                 :            :  * g_dbus_server_get_client_address:
     522                 :            :  * @server: A #GDBusServer.
     523                 :            :  *
     524                 :            :  * Gets a
     525                 :            :  * [D-Bus address](https://dbus.freedesktop.org/doc/dbus-specification.html#addresses)
     526                 :            :  * string that can be used by clients to connect to @server.
     527                 :            :  *
     528                 :            :  * This is valid and non-empty if initializing the #GDBusServer succeeded.
     529                 :            :  *
     530                 :            :  * Returns: (not nullable): A D-Bus address string. Do not free, the string is owned
     531                 :            :  * by @server.
     532                 :            :  *
     533                 :            :  * Since: 2.26
     534                 :            :  */
     535                 :            : const gchar *
     536                 :         33 : g_dbus_server_get_client_address (GDBusServer *server)
     537                 :            : {
     538                 :         33 :   g_return_val_if_fail (G_IS_DBUS_SERVER (server), NULL);
     539                 :         33 :   return server->client_address;
     540                 :            : }
     541                 :            : 
     542                 :            : /**
     543                 :            :  * g_dbus_server_get_guid:
     544                 :            :  * @server: A #GDBusServer.
     545                 :            :  *
     546                 :            :  * Gets the GUID for @server, as provided to g_dbus_server_new_sync().
     547                 :            :  *
     548                 :            :  * Returns: (not nullable): A D-Bus GUID. Do not free this string, it is owned by @server.
     549                 :            :  *
     550                 :            :  * Since: 2.26
     551                 :            :  */
     552                 :            : const gchar *
     553                 :          4 : g_dbus_server_get_guid (GDBusServer *server)
     554                 :            : {
     555                 :          4 :   g_return_val_if_fail (G_IS_DBUS_SERVER (server), NULL);
     556                 :          4 :   return server->guid;
     557                 :            : }
     558                 :            : 
     559                 :            : /**
     560                 :            :  * g_dbus_server_get_flags:
     561                 :            :  * @server: A #GDBusServer.
     562                 :            :  *
     563                 :            :  * Gets the flags for @server.
     564                 :            :  *
     565                 :            :  * Returns: A set of flags from the #GDBusServerFlags enumeration.
     566                 :            :  *
     567                 :            :  * Since: 2.26
     568                 :            :  */
     569                 :            : GDBusServerFlags
     570                 :          4 : g_dbus_server_get_flags (GDBusServer *server)
     571                 :            : {
     572                 :          4 :   g_return_val_if_fail (G_IS_DBUS_SERVER (server), G_DBUS_SERVER_FLAGS_NONE);
     573                 :          4 :   return server->flags;
     574                 :            : }
     575                 :            : 
     576                 :            : /**
     577                 :            :  * g_dbus_server_is_active:
     578                 :            :  * @server: A #GDBusServer.
     579                 :            :  *
     580                 :            :  * Gets whether @server is active.
     581                 :            :  *
     582                 :            :  * Returns: %TRUE if server is active, %FALSE otherwise.
     583                 :            :  *
     584                 :            :  * Since: 2.26
     585                 :            :  */
     586                 :            : gboolean
     587                 :          5 : g_dbus_server_is_active (GDBusServer *server)
     588                 :            : {
     589                 :          5 :   g_return_val_if_fail (G_IS_DBUS_SERVER (server), G_DBUS_SERVER_FLAGS_NONE);
     590                 :          5 :   return server->active;
     591                 :            : }
     592                 :            : 
     593                 :            : /**
     594                 :            :  * g_dbus_server_start:
     595                 :            :  * @server: A #GDBusServer.
     596                 :            :  *
     597                 :            :  * Starts @server.
     598                 :            :  *
     599                 :            :  * Since: 2.26
     600                 :            :  */
     601                 :            : void
     602                 :         25 : g_dbus_server_start (GDBusServer *server)
     603                 :            : {
     604                 :         25 :   g_return_if_fail (G_IS_DBUS_SERVER (server));
     605         [ -  + ]:         25 :   if (server->active)
     606                 :          0 :     return;
     607                 :            :   /* Right now we don't have any transport not using the listener... */
     608                 :         25 :   g_assert (server->is_using_listener);
     609                 :         25 :   server->run_signal_handler_id = g_signal_connect_data (G_SOCKET_SERVICE (server->listener),
     610                 :            :                                                          "run",
     611                 :            :                                                          G_CALLBACK (on_run),
     612                 :            :                                                          g_object_ref (server),
     613                 :            :                                                          (GClosureNotify) g_object_unref,
     614                 :            :                                                          G_CONNECT_DEFAULT);
     615                 :         25 :   g_socket_service_start (G_SOCKET_SERVICE (server->listener));
     616                 :         25 :   server->active = TRUE;
     617                 :         25 :   g_object_notify (G_OBJECT (server), "active");
     618                 :            : }
     619                 :            : 
     620                 :            : /**
     621                 :            :  * g_dbus_server_stop:
     622                 :            :  * @server: A #GDBusServer.
     623                 :            :  *
     624                 :            :  * Stops @server.
     625                 :            :  *
     626                 :            :  * Since: 2.26
     627                 :            :  */
     628                 :            : void
     629                 :         25 : g_dbus_server_stop (GDBusServer *server)
     630                 :            : {
     631                 :         25 :   g_return_if_fail (G_IS_DBUS_SERVER (server));
     632         [ -  + ]:         25 :   if (!server->active)
     633                 :          0 :     return;
     634                 :            :   /* Right now we don't have any transport not using the listener... */
     635                 :         25 :   g_assert (server->is_using_listener);
     636                 :         25 :   g_assert (server->run_signal_handler_id > 0);
     637                 :         25 :   g_clear_signal_handler (&server->run_signal_handler_id, server->listener);
     638                 :         25 :   g_socket_service_stop (G_SOCKET_SERVICE (server->listener));
     639                 :         25 :   server->active = FALSE;
     640                 :         25 :   g_object_notify (G_OBJECT (server), "active");
     641                 :            : 
     642         [ +  + ]:         25 :   if (server->unix_socket_path)
     643                 :            :     {
     644         [ -  + ]:         20 :       if (g_unlink (server->unix_socket_path) != 0)
     645                 :          0 :         g_warning ("Failed to delete %s: %s", server->unix_socket_path, g_strerror (errno));
     646                 :            :     }
     647                 :            : 
     648         [ +  + ]:         25 :   if (server->nonce_file)
     649                 :            :     {
     650         [ -  + ]:          1 :       if (g_unlink (server->nonce_file) != 0)
     651                 :          0 :         g_warning ("Failed to delete %s: %s", server->nonce_file, g_strerror (errno));
     652                 :            :     }
     653                 :            : }
     654                 :            : 
     655                 :            : /* ---------------------------------------------------------------------------------------------------- */
     656                 :            : 
     657                 :            : static gint
     658                 :        144 : random_ascii (void)
     659                 :            : {
     660                 :            :   gint ret;
     661                 :        144 :   ret = g_random_int_range (0, 60);
     662         [ +  + ]:        144 :   if (ret < 25)
     663                 :         66 :     ret += 'A';
     664         [ +  + ]:         78 :   else if (ret < 50)
     665                 :         54 :     ret += 'a' - 25;
     666                 :            :   else
     667                 :         24 :     ret += '0' - 50;
     668                 :        144 :   return ret;
     669                 :            : }
     670                 :            : 
     671                 :            : /* note that address_entry has already been validated => exactly one of path, dir, tmpdir, or abstract keys are set */
     672                 :            : static gboolean
     673                 :         20 : try_unix (GDBusServer  *server,
     674                 :            :           const gchar  *address_entry,
     675                 :            :           GHashTable   *key_value_pairs,
     676                 :            :           GError      **error)
     677                 :            : {
     678                 :            :   gboolean ret;
     679                 :            :   const gchar *path;
     680                 :            :   const gchar *dir;
     681                 :            :   const gchar *tmpdir;
     682                 :            :   const gchar *abstract;
     683                 :            :   GSocketAddress *address;
     684                 :            : 
     685                 :         20 :   ret = FALSE;
     686                 :         20 :   address = NULL;
     687                 :            : 
     688                 :         20 :   path = g_hash_table_lookup (key_value_pairs, "path");
     689                 :         20 :   dir = g_hash_table_lookup (key_value_pairs, "dir");
     690                 :         20 :   tmpdir = g_hash_table_lookup (key_value_pairs, "tmpdir");
     691                 :         20 :   abstract = g_hash_table_lookup (key_value_pairs, "abstract");
     692                 :            : 
     693         [ +  + ]:         20 :   if (path != NULL)
     694                 :            :     {
     695                 :          2 :       address = g_unix_socket_address_new (path);
     696                 :            :     }
     697   [ +  +  +  - ]:         18 :   else if (dir != NULL || tmpdir != NULL)
     698                 :            :     {
     699                 :            :       gint n;
     700                 :            :       GString *s;
     701                 :            :       GError *local_error;
     702                 :            : 
     703                 :         18 :     retry:
     704         [ +  + ]:         18 :       s = g_string_new (tmpdir != NULL ? tmpdir : dir);
     705         [ +  - ]:         18 :       g_string_append (s, "/dbus-");
     706         [ +  + ]:        162 :       for (n = 0; n < 8; n++)
     707         [ +  - ]:        144 :         g_string_append_c (s, random_ascii ());
     708                 :            : 
     709                 :         18 :       address = g_unix_socket_address_new (s->str);
     710                 :         18 :       g_string_free (s, TRUE);
     711                 :            : 
     712                 :         18 :       local_error = NULL;
     713         [ -  + ]:         18 :       if (!g_socket_listener_add_address (server->listener,
     714                 :            :                                           address,
     715                 :            :                                           G_SOCKET_TYPE_STREAM,
     716                 :            :                                           G_SOCKET_PROTOCOL_DEFAULT,
     717                 :            :                                           NULL, /* source_object */
     718                 :            :                                           NULL, /* effective_address */
     719                 :            :                                           &local_error))
     720                 :            :         {
     721   [ #  #  #  # ]:          0 :           if (local_error->domain == G_IO_ERROR && local_error->code == G_IO_ERROR_ADDRESS_IN_USE)
     722                 :            :             {
     723                 :          0 :               g_error_free (local_error);
     724                 :          0 :               goto retry;
     725                 :            :             }
     726                 :          0 :           g_propagate_error (error, local_error);
     727                 :          0 :           goto out;
     728                 :            :         }
     729                 :         18 :       ret = TRUE;
     730                 :         18 :       goto out;
     731                 :            :     }
     732         [ #  # ]:          0 :   else if (abstract != NULL)
     733                 :            :     {
     734         [ #  # ]:          0 :       if (!g_unix_socket_address_abstract_names_supported ())
     735                 :            :         {
     736                 :          0 :           g_set_error_literal (error,
     737                 :            :                                G_IO_ERROR,
     738                 :            :                                G_IO_ERROR_NOT_SUPPORTED,
     739                 :            :                                _("Abstract namespace not supported"));
     740                 :          0 :           goto out;
     741                 :            :         }
     742                 :          0 :       address = g_unix_socket_address_new_with_type (abstract,
     743                 :            :                                                      -1,
     744                 :            :                                                      G_UNIX_SOCKET_ADDRESS_ABSTRACT);
     745                 :            :     }
     746                 :            :   else
     747                 :            :     {
     748                 :            :       g_assert_not_reached ();
     749                 :            :     }
     750                 :            : 
     751         [ -  + ]:          2 :   if (!g_socket_listener_add_address (server->listener,
     752                 :            :                                       address,
     753                 :            :                                       G_SOCKET_TYPE_STREAM,
     754                 :            :                                       G_SOCKET_PROTOCOL_DEFAULT,
     755                 :            :                                       NULL, /* source_object */
     756                 :            :                                       NULL, /* effective_address */
     757                 :            :                                       error))
     758                 :          0 :     goto out;
     759                 :            : 
     760                 :          2 :   ret = TRUE;
     761                 :            : 
     762                 :         20 :  out:
     763                 :            : 
     764         [ +  - ]:         20 :   if (address != NULL)
     765                 :            :     {
     766                 :            :       /* Fill out client_address if the connection attempt worked */
     767         [ +  - ]:         20 :       if (ret)
     768                 :            :         {
     769                 :            :           const char *address_path;
     770                 :            :           char *escaped_path;
     771                 :            : 
     772                 :         20 :           server->is_using_listener = TRUE;
     773                 :         20 :           address_path = g_unix_socket_address_get_path (G_UNIX_SOCKET_ADDRESS (address));
     774                 :         20 :           escaped_path = g_dbus_address_escape_value (address_path);
     775                 :            : 
     776      [ -  +  - ]:         20 :           switch (g_unix_socket_address_get_address_type (G_UNIX_SOCKET_ADDRESS (address)))
     777                 :            :             {
     778                 :          0 :             case G_UNIX_SOCKET_ADDRESS_ABSTRACT:
     779                 :          0 :               server->client_address = g_strdup_printf ("unix:abstract=%s", escaped_path);
     780                 :          0 :               break;
     781                 :            : 
     782                 :         20 :             case G_UNIX_SOCKET_ADDRESS_PATH:
     783                 :         20 :               server->client_address = g_strdup_printf ("unix:path=%s", escaped_path);
     784                 :         20 :               server->unix_socket_path = g_strdup (address_path);
     785                 :         20 :               break;
     786                 :            : 
     787                 :          0 :             default:
     788                 :            :               g_assert_not_reached ();
     789                 :            :               break;
     790                 :            :             }
     791                 :            : 
     792                 :         20 :           g_free (escaped_path);
     793                 :            :         }
     794                 :         20 :       g_object_unref (address);
     795                 :            :     }
     796                 :         20 :   return ret;
     797                 :            : }
     798                 :            : 
     799                 :            : /* ---------------------------------------------------------------------------------------------------- */
     800                 :            : 
     801                 :            : /* note that address_entry has already been validated =>
     802                 :            :  *  both host and port (guaranteed to be a number in [0, 65535]) are set (family is optional)
     803                 :            :  */
     804                 :            : static gboolean
     805                 :          5 : try_tcp (GDBusServer  *server,
     806                 :            :          const gchar  *address_entry,
     807                 :            :          GHashTable   *key_value_pairs,
     808                 :            :          gboolean      do_nonce,
     809                 :            :          GError      **error)
     810                 :            : {
     811                 :            :   gboolean ret;
     812                 :            :   const gchar *host;
     813                 :            :   const gchar *port;
     814                 :            :   gint port_num;
     815                 :            :   GResolver *resolver;
     816                 :            :   GList *resolved_addresses;
     817                 :            :   GList *l;
     818                 :            : 
     819                 :          5 :   ret = FALSE;
     820                 :          5 :   resolver = NULL;
     821                 :          5 :   resolved_addresses = NULL;
     822                 :            : 
     823                 :          5 :   host = g_hash_table_lookup (key_value_pairs, "host");
     824                 :          5 :   port = g_hash_table_lookup (key_value_pairs, "port");
     825                 :            :   /* family = g_hash_table_lookup (key_value_pairs, "family"); */
     826         [ -  + ]:          5 :   if (g_hash_table_lookup (key_value_pairs, "noncefile") != NULL)
     827                 :            :     {
     828                 :          0 :       g_set_error_literal (error,
     829                 :            :                            G_IO_ERROR,
     830                 :            :                            G_IO_ERROR_INVALID_ARGUMENT,
     831                 :            :                            _("Cannot specify nonce file when creating a server"));
     832                 :          0 :       goto out;
     833                 :            :     }
     834                 :            : 
     835         [ -  + ]:          5 :   if (host == NULL)
     836                 :          0 :     host = "localhost";
     837         [ +  - ]:          5 :   if (port == NULL)
     838                 :          5 :     port = "0";
     839                 :          5 :   port_num = strtol (port, NULL, 10);
     840                 :            : 
     841                 :          5 :   resolver = g_resolver_get_default ();
     842                 :          5 :   resolved_addresses = g_resolver_lookup_by_name (resolver,
     843                 :            :                                                   host,
     844                 :            :                                                   NULL,
     845                 :            :                                                   error);
     846         [ -  + ]:          5 :   if (resolved_addresses == NULL)
     847                 :          0 :     goto out;
     848                 :            : 
     849                 :            :   /* TODO: handle family */
     850         [ +  + ]:         10 :   for (l = resolved_addresses; l != NULL; l = l->next)
     851                 :            :     {
     852                 :          5 :       GInetAddress *address = G_INET_ADDRESS (l->data);
     853                 :            :       GSocketAddress *socket_address;
     854                 :            :       GSocketAddress *effective_address;
     855                 :            : 
     856                 :          5 :       socket_address = g_inet_socket_address_new (address, port_num);
     857         [ -  + ]:          5 :       if (!g_socket_listener_add_address (server->listener,
     858                 :            :                                           socket_address,
     859                 :            :                                           G_SOCKET_TYPE_STREAM,
     860                 :            :                                           G_SOCKET_PROTOCOL_TCP,
     861                 :            :                                           NULL, /* GObject *source_object */
     862                 :            :                                           &effective_address,
     863                 :            :                                           error))
     864                 :            :         {
     865                 :          0 :           g_object_unref (socket_address);
     866                 :          0 :           goto out;
     867                 :            :         }
     868         [ +  - ]:          5 :       if (port_num == 0)
     869                 :            :         /* make sure we allocate the same port number for other listeners */
     870                 :          5 :         port_num = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (effective_address));
     871                 :            : 
     872                 :          5 :       g_object_unref (effective_address);
     873                 :          5 :       g_object_unref (socket_address);
     874                 :            :     }
     875                 :            : 
     876         [ +  + ]:          5 :   if (do_nonce)
     877                 :            :     {
     878                 :            :       gint fd;
     879                 :            :       guint n;
     880                 :            :       gsize bytes_written;
     881                 :            :       gsize bytes_remaining;
     882                 :            :       char *file_escaped;
     883                 :            :       char *host_escaped;
     884                 :            : 
     885                 :          1 :       server->nonce = g_new0 (guchar, 16);
     886         [ +  + ]:         17 :       for (n = 0; n < 16; n++)
     887                 :         16 :         server->nonce[n] = g_random_int_range (0, 256);
     888                 :          1 :       fd = g_file_open_tmp ("gdbus-nonce-file-XXXXXX",
     889                 :            :                             &server->nonce_file,
     890                 :            :                             error);
     891         [ +  - ]:          1 :       if (fd == -1)
     892                 :            :         {
     893                 :          0 :           g_socket_listener_close (server->listener);
     894                 :          0 :           goto out;
     895                 :            :         }
     896                 :          1 :     again:
     897                 :          1 :       bytes_written = 0;
     898                 :          1 :       bytes_remaining = 16;
     899         [ +  + ]:          2 :       while (bytes_remaining > 0)
     900                 :            :         {
     901                 :            :           gssize size;
     902                 :            :           int errsv;
     903                 :            : 
     904                 :          1 :           size = write (fd, server->nonce + bytes_written, bytes_remaining);
     905                 :          1 :           errsv = errno;
     906         [ -  + ]:          1 :           if (size == -1)
     907                 :            :             {
     908         [ #  # ]:          0 :               if (errsv == EINTR)
     909                 :          0 :                 goto again;
     910                 :          0 :               g_set_error (error,
     911                 :            :                            G_IO_ERROR,
     912                 :          0 :                            g_io_error_from_errno (errsv),
     913                 :            :                            _("Error writing nonce file at “%s”: %s"),
     914                 :            :                            server->nonce_file,
     915                 :            :                            g_strerror (errsv));
     916                 :          0 :               goto out;
     917                 :            :             }
     918                 :          1 :           bytes_written += size;
     919                 :          1 :           bytes_remaining -= size;
     920                 :            :         }
     921         [ -  + ]:          1 :       if (!g_close (fd, error))
     922                 :          0 :         goto out;
     923                 :          1 :       host_escaped = g_dbus_address_escape_value (host);
     924                 :          1 :       file_escaped = g_dbus_address_escape_value (server->nonce_file);
     925                 :          1 :       server->client_address = g_strdup_printf ("nonce-tcp:host=%s,port=%d,noncefile=%s",
     926                 :            :                                                 host_escaped,
     927                 :            :                                                 port_num,
     928                 :            :                                                 file_escaped);
     929                 :          1 :       g_free (host_escaped);
     930                 :          1 :       g_free (file_escaped);
     931                 :            :     }
     932                 :            :   else
     933                 :            :     {
     934                 :          4 :       server->client_address = g_strdup_printf ("tcp:host=%s,port=%d", host, port_num);
     935                 :            :     }
     936                 :          5 :   server->is_using_listener = TRUE;
     937                 :          5 :   ret = TRUE;
     938                 :            : 
     939                 :          5 :  out:
     940                 :          5 :   g_list_free_full (resolved_addresses, g_object_unref);
     941         [ +  - ]:          5 :   if (resolver)
     942                 :          5 :     g_object_unref (resolver);
     943                 :          5 :   return ret;
     944                 :            : }
     945                 :            : 
     946                 :            : /* ---------------------------------------------------------------------------------------------------- */
     947                 :            : 
     948                 :            : typedef struct
     949                 :            : {
     950                 :            :   GDBusServer *server;
     951                 :            :   GDBusConnection *connection;
     952                 :            : } EmitIdleData;
     953                 :            : 
     954                 :            : static void
     955                 :         20 : emit_idle_data_free (EmitIdleData *data)
     956                 :            : {
     957                 :         20 :   g_object_unref (data->server);
     958                 :         20 :   g_object_unref (data->connection);
     959                 :         20 :   g_free (data);
     960                 :         20 : }
     961                 :            : 
     962                 :            : static gboolean
     963                 :         20 : emit_new_connection_in_idle (gpointer user_data)
     964                 :            : {
     965                 :         20 :   EmitIdleData *data = user_data;
     966                 :            :   gboolean claimed;
     967                 :            : 
     968                 :         20 :   claimed = FALSE;
     969                 :         20 :   g_signal_emit (data->server,
     970                 :            :                  _signals[NEW_CONNECTION_SIGNAL],
     971                 :            :                  0,
     972                 :            :                  data->connection,
     973                 :            :                  &claimed);
     974                 :            : 
     975         [ +  + ]:         20 :   if (claimed)
     976                 :         15 :     g_dbus_connection_start_message_processing (data->connection);
     977                 :         20 :   g_object_unref (data->connection);
     978                 :            : 
     979                 :         20 :   return FALSE;
     980                 :            : }
     981                 :            : 
     982                 :            : /* Called in new thread */
     983                 :            : static gboolean
     984                 :        221 : on_run (GSocketService    *service,
     985                 :            :         GSocketConnection *socket_connection,
     986                 :            :         GObject           *source_object,
     987                 :            :         gpointer           user_data)
     988                 :            : {
     989                 :        221 :   GDBusServer *server = G_DBUS_SERVER (user_data);
     990                 :            :   GDBusConnection *connection;
     991                 :            :   GDBusConnectionFlags connection_flags;
     992                 :            : 
     993         [ +  + ]:        221 :   if (server->nonce != NULL)
     994                 :            :     {
     995                 :            :       gchar buf[16];
     996                 :            :       gsize bytes_read;
     997                 :            : 
     998         [ -  + ]:          4 :       if (!g_input_stream_read_all (g_io_stream_get_input_stream (G_IO_STREAM (socket_connection)),
     999                 :            :                                     buf,
    1000                 :            :                                     16,
    1001                 :            :                                     &bytes_read,
    1002                 :            :                                     NULL,  /* GCancellable */
    1003                 :            :                                     NULL)) /* GError */
    1004                 :          3 :         goto out;
    1005                 :            : 
    1006         [ +  + ]:          4 :       if (bytes_read != 16)
    1007                 :          2 :         goto out;
    1008                 :            : 
    1009         [ +  + ]:          2 :       if (memcmp (buf, server->nonce, 16) != 0)
    1010                 :          1 :         goto out;
    1011                 :            :     }
    1012                 :            : 
    1013                 :        218 :   connection_flags =
    1014                 :            :     G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER |
    1015                 :            :     G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING;
    1016         [ +  + ]:        218 :   if (server->flags & G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS)
    1017                 :         44 :     connection_flags |= G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS;
    1018         [ +  + ]:        218 :   if (server->flags & G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER)
    1019                 :         21 :     connection_flags |= G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER;
    1020                 :            : 
    1021                 :        218 :   connection = g_dbus_connection_new_sync (G_IO_STREAM (socket_connection),
    1022                 :        218 :                                            server->guid,
    1023                 :            :                                            connection_flags,
    1024                 :            :                                            server->authentication_observer,
    1025                 :            :                                            NULL,  /* GCancellable */
    1026                 :            :                                            NULL); /* GError */
    1027         [ +  + ]:        218 :   if (connection == NULL)
    1028                 :          9 :       goto out;
    1029                 :            : 
    1030         [ +  + ]:        209 :   if (server->flags & G_DBUS_SERVER_FLAGS_RUN_IN_THREAD)
    1031                 :            :     {
    1032                 :            :       gboolean claimed;
    1033                 :            : 
    1034                 :        189 :       claimed = FALSE;
    1035                 :        189 :       g_signal_emit (server,
    1036                 :            :                      _signals[NEW_CONNECTION_SIGNAL],
    1037                 :            :                      0,
    1038                 :            :                      connection,
    1039                 :            :                      &claimed);
    1040         [ +  - ]:        189 :       if (claimed)
    1041                 :        189 :         g_dbus_connection_start_message_processing (connection);
    1042                 :        189 :       g_object_unref (connection);
    1043                 :            :     }
    1044                 :            :   else
    1045                 :            :     {
    1046                 :            :       GSource *idle_source;
    1047                 :            :       EmitIdleData *data;
    1048                 :            : 
    1049                 :         20 :       data = g_new0 (EmitIdleData, 1);
    1050                 :         20 :       data->server = g_object_ref (server);
    1051                 :         20 :       data->connection = g_object_ref (connection);
    1052                 :            : 
    1053                 :         20 :       idle_source = g_idle_source_new ();
    1054                 :         20 :       g_source_set_priority (idle_source, G_PRIORITY_DEFAULT);
    1055                 :         20 :       g_source_set_callback (idle_source,
    1056                 :            :                              emit_new_connection_in_idle,
    1057                 :            :                              data,
    1058                 :            :                              (GDestroyNotify) emit_idle_data_free);
    1059                 :         20 :       g_source_set_static_name (idle_source, "[gio] emit_new_connection_in_idle");
    1060                 :         20 :       g_source_attach (idle_source, server->main_context_at_construction);
    1061                 :         20 :       g_source_unref (idle_source);
    1062                 :            :     }
    1063                 :            : 
    1064                 :        221 :  out:
    1065                 :        221 :   return TRUE;
    1066                 :            : }
    1067                 :            : 
    1068                 :            : static gboolean
    1069                 :         25 : initable_init (GInitable     *initable,
    1070                 :            :                GCancellable  *cancellable,
    1071                 :            :                GError       **error)
    1072                 :            : {
    1073                 :         25 :   GDBusServer *server = G_DBUS_SERVER (initable);
    1074                 :            :   gboolean ret;
    1075                 :            :   guint n;
    1076                 :            :   gchar **addr_array;
    1077                 :            :   GError *last_error;
    1078                 :            : 
    1079                 :         25 :   ret = FALSE;
    1080                 :         25 :   addr_array = NULL;
    1081                 :         25 :   last_error = NULL;
    1082                 :            : 
    1083         [ -  + ]:         25 :   if (!g_dbus_is_guid (server->guid))
    1084                 :            :     {
    1085                 :          0 :       g_set_error (&last_error,
    1086                 :            :                    G_IO_ERROR,
    1087                 :            :                    G_IO_ERROR_INVALID_ARGUMENT,
    1088                 :            :                    _("The string “%s” is not a valid D-Bus GUID"),
    1089                 :            :                    server->guid);
    1090                 :          0 :       goto out;
    1091                 :            :     }
    1092                 :            : 
    1093                 :         25 :   server->listener = G_SOCKET_LISTENER (g_threaded_socket_service_new (-1));
    1094                 :            : 
    1095                 :         25 :   addr_array = g_strsplit (server->address, ";", 0);
    1096                 :         25 :   last_error = NULL;
    1097   [ -  +  +  - ]:         25 :   for (n = 0; addr_array != NULL && addr_array[n] != NULL; n++)
    1098                 :            :     {
    1099                 :         25 :       const gchar *address_entry = addr_array[n];
    1100                 :            :       GHashTable *key_value_pairs;
    1101                 :            :       gchar *transport_name;
    1102                 :            :       GError *this_error;
    1103                 :            : 
    1104                 :         25 :       this_error = NULL;
    1105         [ +  - ]:         25 :       if (g_dbus_is_supported_address (address_entry,
    1106         [ +  - ]:         25 :                                        &this_error) &&
    1107                 :         25 :           _g_dbus_address_parse_entry (address_entry,
    1108                 :            :                                        &transport_name,
    1109                 :            :                                        &key_value_pairs,
    1110                 :            :                                        &this_error))
    1111                 :            :         {
    1112                 :            : 
    1113                 :            :           if (FALSE)
    1114                 :            :             {
    1115                 :            :             }
    1116         [ +  + ]:         25 :           else if (g_strcmp0 (transport_name, "unix") == 0)
    1117                 :         20 :             ret = try_unix (server, address_entry, key_value_pairs, &this_error);
    1118         [ +  + ]:          5 :           else if (g_strcmp0 (transport_name, "tcp") == 0)
    1119                 :          4 :             ret = try_tcp (server, address_entry, key_value_pairs, FALSE, &this_error);
    1120         [ +  - ]:          1 :           else if (g_strcmp0 (transport_name, "nonce-tcp") == 0)
    1121                 :          1 :             ret = try_tcp (server, address_entry, key_value_pairs, TRUE, &this_error);
    1122                 :            :           else
    1123                 :          0 :             g_set_error (&this_error,
    1124                 :            :                          G_IO_ERROR,
    1125                 :            :                          G_IO_ERROR_INVALID_ARGUMENT,
    1126                 :            :                          _("Cannot listen on unsupported transport “%s”"),
    1127                 :            :                          transport_name);
    1128                 :            : 
    1129                 :         25 :           g_free (transport_name);
    1130         [ +  - ]:         25 :           if (key_value_pairs != NULL)
    1131                 :         25 :             g_hash_table_unref (key_value_pairs);
    1132                 :            : 
    1133         [ +  - ]:         25 :           if (ret)
    1134                 :            :             {
    1135                 :         25 :               g_assert (this_error == NULL);
    1136                 :         25 :               goto out;
    1137                 :            :             }
    1138                 :            :         }
    1139                 :            : 
    1140         [ #  # ]:          0 :       if (this_error != NULL)
    1141                 :            :         {
    1142         [ #  # ]:          0 :           if (last_error != NULL)
    1143                 :          0 :             g_error_free (last_error);
    1144                 :          0 :           last_error = this_error;
    1145                 :            :         }
    1146                 :            :     }
    1147                 :            : 
    1148                 :          0 :  out:
    1149                 :            : 
    1150                 :         25 :   g_strfreev (addr_array);
    1151                 :            : 
    1152         [ +  - ]:         25 :   if (ret)
    1153                 :            :     {
    1154                 :         25 :       g_clear_error (&last_error);
    1155                 :            :     }
    1156                 :            :   else
    1157                 :            :     {
    1158                 :          0 :       g_assert (last_error != NULL);
    1159                 :          0 :       g_propagate_error (error, last_error);
    1160                 :            :     }
    1161                 :         25 :   return ret;
    1162                 :            : }
    1163                 :            : 
    1164                 :            : 
    1165                 :            : static void
    1166                 :          6 : initable_iface_init (GInitableIface *initable_iface)
    1167                 :            : {
    1168                 :          6 :   initable_iface->init = initable_init;
    1169                 :          6 : }
    1170                 :            : 
    1171                 :            : /* ---------------------------------------------------------------------------------------------------- */

Generated by: LCOV version 1.14