static void
tls_handler_init_async (GAsyncInitable *initable,
                        gint io_priority,
                        GCancellable *cancellable,
                        GAsyncReadyCallback callback,
                        gpointer user_data)
{
    GVariant *properties;
    const gchar *cert_object_path;
    const gchar *bus_name;
    GError *error = NULL;
    GQuark features[] = { TP_TLS_CERTIFICATE_FEATURE_CORE, 0 };
    /*
     * Used when channel doesn't implement ReferenceIdentities. A GStrv
     * with [0] the hostname, and [1] a NULL terminator.
     */
    gchar *default_identities[2];
    EmpathyServerTLSHandler *self = EMPATHY_SERVER_TLS_HANDLER (initable);
    EmpathyServerTLSHandlerPriv *priv = GET_PRIV (self);

    g_assert (priv->channel != NULL);

    priv->async_init_res = g_simple_async_result_new (G_OBJECT (self),
                           callback, user_data, empathy_server_tls_handler_new_async);
    properties = tp_channel_dup_immutable_properties (priv->channel);

    g_variant_lookup (properties,
                      TP_PROP_CHANNEL_TYPE_SERVER_TLS_CONNECTION_HOSTNAME,
                      "s", &priv->hostname);

    DEBUG ("Received hostname: %s", priv->hostname);

    g_variant_lookup (properties,
                      TP_PROP_CHANNEL_TYPE_SERVER_TLS_CONNECTION_REFERENCE_IDENTITIES,
                      "^as", &priv->reference_identities);

    /*
     * If the channel doesn't implement the ReferenceIdentities parameter
     * then fallback to the hostname.
     */
    if (priv->reference_identities == NULL)
    {
        default_identities[0] = (gchar *) priv->hostname;
        default_identities[1] = NULL;
        priv->reference_identities = g_strdupv (default_identities);
    }
    else
    {
#ifdef ENABLE_DEBUG
        gchar *output = g_strjoinv (", ", (gchar **) priv->reference_identities);
        DEBUG ("Received reference identities: %s", output);
        g_free (output);
#endif /* ENABLE_DEBUG */
    }

    g_variant_lookup (properties,
                      TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION ".ServerCertificate",
                      "&o", &cert_object_path);
    bus_name = tp_proxy_get_bus_name (TP_PROXY (priv->channel));

    DEBUG ("Creating an TpTLSCertificate for path %s, bus name %s",
           cert_object_path, bus_name);

    priv->certificate = tp_tls_certificate_new (TP_PROXY (priv->channel),
                        cert_object_path, &error);

    g_variant_unref (properties);

    if (error != NULL)
    {
        DEBUG ("Unable to create the TpTLSCertificate: error %s",
               error->message);

        g_simple_async_result_set_from_error (priv->async_init_res, error);
        g_simple_async_result_complete_in_idle (priv->async_init_res);

        g_error_free (error);
        tp_clear_object (&priv->async_init_res);

        return;
    }

    tp_proxy_prepare_async (priv->certificate, features,
                            tls_certificate_prepared_cb, self);
}
GList *
_mcd_client_registry_list_possible_handlers (McdClientRegistry *self,
    const gchar *preferred_handler,
    GVariant *request_props,
    TpChannel *channel,
    const gchar *must_have_unique_name)
{
  GList *handlers = NULL;
  GList *handlers_iter;
  GHashTableIter client_iter;
  gpointer client_p;

  _mcd_client_registry_init_hash_iter (self, &client_iter);

  while (g_hash_table_iter_next (&client_iter, NULL, &client_p))
    {
      McdClientProxy *client = MCD_CLIENT_PROXY (client_p);
      gsize quality;

      if (must_have_unique_name != NULL &&
          tp_strdiff (must_have_unique_name,
            _mcd_client_proxy_get_unique_name (client)))
        {
          /* we're trying to redispatch to an existing handler, and this is
           * not it */
          continue;
        }

      if (!tp_proxy_has_interface_by_id (client,
            TP_IFACE_QUARK_CLIENT_HANDLER))
        {
            /* not a handler at all */
            continue;
        }

      if (channel == NULL)
        {
          /* We don't know the channel's properties (the next part will not
           * execute), so we must work out the quality of match from the
           * channel request. We can assume that the request will return one
           * channel, with the requested properties, plus Requested == TRUE.
           */
          g_assert (request_props != NULL);
          quality = _mcd_client_match_filters (request_props,
              _mcd_client_proxy_get_handler_filters (client), TRUE);
        }
      else
        {
          GVariant *properties;

          g_assert (TP_IS_CHANNEL (channel));
          properties = tp_channel_dup_immutable_properties (channel);
          quality = _mcd_client_match_filters (properties,
              _mcd_client_proxy_get_handler_filters (client), FALSE);
          g_variant_unref (properties);
        }

      if (quality > 0)
        {
          PossibleHandler *ph = g_slice_new0 (PossibleHandler);

          ph->client = client;
          ph->bypass = _mcd_client_proxy_get_bypass_approval (client);
          ph->quality = quality;

          handlers = g_list_prepend (handlers, ph);
        }
    }

  /* if no handlers can take them all, fail - unless we're operating on
   * a request that specified a preferred handler, in which case assume
   * it's suitable */
  if (handlers == NULL)
    {
      McdClientProxy *client;

      if (preferred_handler == NULL || preferred_handler[0] == '\0')
        {
          return NULL;
        }

      client = _mcd_client_registry_lookup (self, preferred_handler);

      if (client == NULL)
        {
          return NULL;
        }

      return g_list_append (NULL, client);
    }

  /* We have at least one handler that can take the whole batch. Sort
   * the possible handlers, most preferred first (i.e. sort by ascending
   * quality then reverse) */
  handlers = g_list_sort (handlers, possible_handler_cmp);
  handlers = g_list_reverse (handlers);

  /* convert in-place from a list of PossibleHandler to a list of
   * McdClientProxy */
  for (handlers_iter = handlers;
       handlers_iter != NULL;
       handlers_iter = handlers_iter->next)
    {
      PossibleHandler *ph = handlers_iter->data;

      handlers_iter->data = ph->client;
      g_slice_free (PossibleHandler, ph);
    }

  return handlers;
}