Example #1
0
static gboolean
example_csh_room_manager_request (ExampleCSHRoomManager *self,
                                  gpointer request_token,
                                  GHashTable *request_properties,
                                  gboolean require_new)
{
  TpHandle handle;
  ExampleCSHRoomChannel *chan;
  GError *error = NULL;

  if (tp_strdiff (tp_asv_get_string (request_properties,
          TP_PROP_CHANNEL_CHANNEL_TYPE),
      TP_IFACE_CHANNEL_TYPE_TEXT))
    {
      return FALSE;
    }

  if (tp_asv_get_uint32 (request_properties,
      TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, NULL) != TP_HANDLE_TYPE_ROOM)
    {
      return FALSE;
    }

  handle = tp_asv_get_uint32 (request_properties,
      TP_PROP_CHANNEL_TARGET_HANDLE, NULL);
  g_assert (handle != 0);

  if (tp_channel_manager_asv_has_unknown_properties (request_properties,
        fixed_properties, allowed_properties, &error))
    {
      goto error;
    }

  chan = g_hash_table_lookup (self->priv->channels, GUINT_TO_POINTER (handle));

  if (chan == NULL)
    {
      new_channel (self, handle, self->priv->conn->self_handle,
          request_token);
    }
  else if (require_new)
    {
      g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
          "A Text channel for room #%u already exists", handle);
      goto error;
    }
  else
    {
      tp_channel_manager_emit_request_already_satisfied (self,
          request_token, TP_EXPORTABLE_CHANNEL (chan));
    }

  return TRUE;

error:
  tp_channel_manager_emit_request_failed (self, request_token,
      error->domain, error->code, error->message);
  g_error_free (error);
  return TRUE;
}
Example #2
0
static gboolean
gabble_im_factory_requestotron (GabbleImFactory *self,
                                gpointer request_token,
                                GHashTable *request_properties,
                                gboolean require_new)
{
  TpHandle handle;
  GError *error = NULL;
  TpExportableChannel *channel;

  if (tp_strdiff (tp_asv_get_string (request_properties,
          TP_IFACE_CHANNEL ".ChannelType"), TP_IFACE_CHANNEL_TYPE_TEXT))
    return FALSE;

  if (tp_asv_get_uint32 (request_properties,
        TP_IFACE_CHANNEL ".TargetHandleType", NULL) != TP_HANDLE_TYPE_CONTACT)
    return FALSE;

  /* validity already checked by TpBaseConnection */
  handle = tp_asv_get_uint32 (request_properties,
      TP_IFACE_CHANNEL ".TargetHandle", NULL);
  g_assert (handle != 0);

  if (tp_channel_manager_asv_has_unknown_properties (request_properties,
          im_channel_fixed_properties, im_channel_allowed_properties,
          &error))
    goto error;

  channel = g_hash_table_lookup (self->priv->channels,
      GUINT_TO_POINTER (handle));

  if (channel == NULL)
    {
      new_im_channel (self, handle, request_token);
      return TRUE;
    }

  if (require_new)
    {
      g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
          "Already chatting with contact #%u in another channel", handle);
      goto error;
    }

  tp_channel_manager_emit_request_already_satisfied (self, request_token,
      channel);
  return TRUE;

error:
  tp_channel_manager_emit_request_failed (self, request_token,
      error->domain, error->code, error->message);
  g_error_free (error);
  return TRUE;
}
static gboolean
ring_text_requestotron(RingTextManager *self,
  gpointer request,
  GHashTable *properties,
  gboolean require_mine)
{
  RingTextManagerPrivate *priv = self->priv;
  TpHandle initiator, target;

  initiator = priv->connection->parent.self_handle;
  target = tp_asv_get_uint32(properties, TP_IFACE_CHANNEL ".TargetHandle", NULL);

  if (target == 0 ||
    target == priv->connection->parent.self_handle ||
    target == priv->connection->anon_handle)
    return FALSE;

  if (!ring_properties_satisfy(properties,
      ring_text_channel_fixed_properties(),
      ring_text_channel_allowed_properties))
    return FALSE;

  if (!tp_asv_get_sms_channel (properties))
    return FALSE;

  ring_text_manager_request(self, request, initiator, target, require_mine, 0);
  return TRUE;
}
static void tls_certificate_got_all_handler(TpProxy *proxy,
			GHashTable *properties, const GError *error,
			gpointer user_data, GObject *weak_object)
{
	HevImpathyTLSCertificate *self = HEV_IMPATHY_TLS_CERTIFICATE(weak_object);
	HevImpathyTLSCertificatePrivate *priv =
		HEV_IMPATHY_TLS_CERTIFICATE_GET_PRIVATE(self);
	GPtrArray *cert_data = NULL;

	g_debug("%s:%d[%s]", __FILE__, __LINE__, __FUNCTION__);

	if(NULL != error)
	{
		g_simple_async_result_set_from_error(priv->async_prepare_res, error);
		g_simple_async_result_complete(priv->async_prepare_res);
		tp_clear_object(&priv->async_prepare_res);

		return;
	}

	priv->cert_type = g_strdup(tp_asv_get_string(properties,
					"CertificateType"));
	priv->state = tp_asv_get_uint32(properties, "State", NULL);

	cert_data = tp_asv_get_boxed(properties, "CertificateChainData",
				TP_ARRAY_TYPE_UCHAR_ARRAY_LIST);
	g_assert(NULL != cert_data);
	priv->cert_data = g_boxed_copy(TP_ARRAY_TYPE_UCHAR_ARRAY_LIST,
				cert_data);

	priv->is_prepared = TRUE;

	g_simple_async_result_complete(priv->async_prepare_res);
	tp_clear_object(&priv->async_prepare_res);
}
Example #5
0
gboolean
_capabilities_has_stream_tube (TpCapabilities *caps)
{
  GPtrArray *classes;
  guint i;

  if (caps == NULL)
    return FALSE;

  classes = tp_capabilities_get_channel_classes (caps);
  for (i = 0; i < classes->len; i++)
    {
      GValueArray *arr = g_ptr_array_index (classes, i);
      GHashTable *fixed;
      const gchar *chan_type;
      const gchar *service;
      TpHandleType handle_type;

      fixed = g_value_get_boxed (g_value_array_get_nth (arr, 0));
      chan_type = tp_asv_get_string (fixed, TP_PROP_CHANNEL_CHANNEL_TYPE);
      service = tp_asv_get_string (fixed,
          TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SERVICE);
      handle_type = tp_asv_get_uint32 (fixed,
          TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, NULL);

      if (!tp_strdiff (chan_type, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE) &&
          handle_type == TP_HANDLE_TYPE_CONTACT &&
          (!tp_capabilities_is_specific_to_contact (caps) ||
           !tp_strdiff (service, TUBE_SERVICE)))
        return TRUE;
    }

  return FALSE;
}
static void
iterate_on_channels (EmpathyTpContactList *list,
		     const GPtrArray *channels)
{
	guint i;

	for (i = 0; i < channels->len ; i++) {
		GValueArray *arr = g_ptr_array_index (channels, i);
		const gchar *path;
		GHashTable *properties;
		TpHandleType handle_type;

		path = g_value_get_boxed (g_value_array_get_nth (arr, 0));
		properties = g_value_get_boxed (g_value_array_get_nth (arr, 1));

		if (tp_strdiff (tp_asv_get_string (properties,
				TP_IFACE_CHANNEL ".ChannelType"),
		    TP_IFACE_CHANNEL_TYPE_CONTACT_LIST))
			continue;

		if (tp_asv_get_string (properties, TP_IFACE_CHANNEL ".TargetID") == NULL)
			continue;

		handle_type = tp_asv_get_uint32 (properties,
			TP_IFACE_CHANNEL ".TargetHandleType", NULL);

		if (handle_type != TP_HANDLE_TYPE_GROUP)
			continue;

		tp_contact_list_group_add_channel (list, path, properties);
	}
}
Example #7
0
static void
on_group_contacts_changed (TpChannel  *channel,
                           GPtrArray  *added,
                           GPtrArray  *removed,
                           GPtrArray  *local_pending,
                           GPtrArray  *remote_pending,
                           TpContact  *actor,
                           GHashTable *details,
                           gpointer    user_data)
{
  TpChannelGroupChangeReason reason;
  const char *message;
  int i;

  reason = tp_asv_get_uint32 (details, "change-reason", NULL);
  message = tp_asv_get_string (details, "message");

  switch (reason)
    {
    case TP_CHANNEL_GROUP_CHANGE_REASON_RENAMED:
      g_signal_emit (user_data, signals[MEMBER_RENAMED], 0,
                     g_ptr_array_index (removed, 0),
                     g_ptr_array_index (added, 0));
      break;
    case TP_CHANNEL_GROUP_CHANGE_REASON_OFFLINE:
      for (i = 0; i < removed->len; i++)
        g_signal_emit (user_data, signals[MEMBER_DISCONNECTED], 0,
                       g_ptr_array_index (removed, i), message);
      break;
    case TP_CHANNEL_GROUP_CHANGE_REASON_KICKED:
      for (i = 0; i < removed->len; i++)
        g_signal_emit (user_data, signals[MEMBER_KICKED], 0,
                       g_ptr_array_index (removed, i), actor);
      break;
    case TP_CHANNEL_GROUP_CHANGE_REASON_BANNED:
      for (i = 0; i < removed->len; i++)
        g_signal_emit (user_data, signals[MEMBER_BANNED], 0,
                       g_ptr_array_index (removed, i), actor);
      break;
    case TP_CHANNEL_GROUP_CHANGE_REASON_NONE:
      for (i = 0; i < removed->len; i++)
        g_signal_emit (user_data, signals[MEMBER_LEFT], 0,
                       g_ptr_array_index (removed, i), message);
      for (i = 0; i < added->len; i++)
        g_signal_emit (user_data, signals[MEMBER_JOINED], 0,
                       g_ptr_array_index (added, i));
      break;
    }

  g_signal_emit (user_data, signals[MEMBERS_CHANGED], 0);
}
static EmpathyCapabilities
channel_classes_to_capabilities (GPtrArray *classes,
				 gboolean audio_video)
{
	EmpathyCapabilities capabilities = 0;
	guint i;

	for (i = 0; i < classes->len; i++) {
		GValueArray *class_struct;
		GHashTable *fixed_prop;
		GStrv allowed_prop;
		TpHandleType handle_type;
		const gchar *chan_type;

		class_struct = g_ptr_array_index (classes, i);
		fixed_prop = g_value_get_boxed (g_value_array_get_nth (class_struct, 0));
		allowed_prop = g_value_get_boxed (g_value_array_get_nth (class_struct, 1));

		handle_type = tp_asv_get_uint32 (fixed_prop,
			TP_IFACE_CHANNEL ".TargetHandleType", NULL);
		if (handle_type != TP_HANDLE_TYPE_CONTACT)
			continue;

		chan_type = tp_asv_get_string (fixed_prop,
			TP_IFACE_CHANNEL ".ChannelType");

		if (!tp_strdiff (chan_type, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER)) {
			capabilities |= EMPATHY_CAPABILITIES_FT;
		}

		else if (!tp_strdiff (chan_type, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE)) {
			capabilities |= EMPATHY_CAPABILITIES_STREAM_TUBE;
		}
		else if (audio_video && !tp_strdiff (chan_type,
			TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA)) {
			guint j;

			for (j = 0; allowed_prop[j] != NULL; j++) {
				if (!tp_strdiff (allowed_prop[j],
						TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA ".InitialAudio"))
					capabilities |= EMPATHY_CAPABILITIES_AUDIO;
				else if (!tp_strdiff (allowed_prop[j],
						TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA ".InitialVideo"))
					capabilities |= EMPATHY_CAPABILITIES_VIDEO;
			}
		}
	}

	return capabilities;
}
guint
_tp_signalled_message_get_pending_message_id (TpMessage *message,
    gboolean *valid)
{
  const GHashTable *part0;

  g_return_val_if_fail (TP_IS_SIGNALLED_MESSAGE (message), 0);
  g_return_val_if_fail (valid != NULL, 0);

  part0 = tp_message_peek (message, 0);
  if (part0 == NULL)
    {
      *valid = FALSE;
      return 0;
    }

  return tp_asv_get_uint32 (part0, "pending-message-id", valid);
}
static void
got_all_properties_cb (TpProxy *proxy,
    GHashTable *properties,
    const GError *error,
    gpointer user_data,
    GObject *weak_object)
{
  TpCallStream *self = (TpCallStream *) proxy;
  const gchar * const *interfaces;
  GHashTable *remote_members;
  GHashTable *identifiers;
  GHashTable *contacts;

  if (error != NULL)
    {
      DEBUG ("Could not get the call stream properties: %s", error->message);
      _tp_proxy_set_feature_prepared (proxy,
          TP_CALL_STREAM_FEATURE_CORE, FALSE);
      return;
    }

  self->priv->properties_retrieved = TRUE;

  interfaces = tp_asv_get_boxed (properties,
      "Interfaces", G_TYPE_STRV);
  remote_members = tp_asv_get_boxed (properties,
      "RemoteMembers", TP_HASH_TYPE_CONTACT_SENDING_STATE_MAP),
  identifiers = tp_asv_get_boxed (properties,
      "RemoteMemberIdentifiers", TP_HASH_TYPE_HANDLE_IDENTIFIER_MAP);
  self->priv->local_sending_state = tp_asv_get_uint32 (properties,
      "LocalSendingState", NULL);
  self->priv->can_request_receiving = tp_asv_get_boolean (properties,
      "CanRequestReceiving", NULL);

  tp_proxy_add_interfaces ((TpProxy *) self, interfaces);

  contacts = _tp_call_members_convert_table (self->priv->connection,
      remote_members, identifiers);
  update_remote_members (self, contacts, NULL);
  g_hash_table_unref (contacts);

  _tp_proxy_set_feature_prepared (proxy, TP_CALL_STREAM_FEATURE_CORE, TRUE);
}
Example #11
0
static void
channel_prepared_cb (
    GObject *source,
    GAsyncResult *result,
    gpointer user_data)
{
  TpFileTransferChannel *channel = TP_FILE_TRANSFER_CHANNEL (source);
  CallbacksData *cb_data = user_data;
  EmpathyFTHandler *handler = cb_data->handler;
  EmpathyFTHandlerPriv *priv = handler->priv;
  GHashTable *properties;
  GError *error = NULL;

  if (!tp_proxy_prepare_finish (channel, result, &error))
    {
      if (!g_cancellable_is_cancelled (priv->cancellable))
        g_cancellable_cancel (priv->cancellable);

      cb_data->callback (handler, error, cb_data->user_data);
      g_clear_error (&error);
      callbacks_data_free (cb_data);
      return;
    }
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
  properties = tp_channel_borrow_immutable_properties (TP_CHANNEL (channel));
  #pragma GCC diagnostic pop

  priv->content_hash = g_strdup (
      tp_asv_get_string (properties, "ContentHash"));

  priv->content_hash_type = tp_asv_get_uint32 (
      properties, "ContentHashType", NULL);

  priv->contact = g_object_ref (tp_channel_get_target_contact (TP_CHANNEL (channel)));

  cb_data->callback (handler, NULL, cb_data->user_data);
}
static void
tls_certificate_got_all_cb (TpProxy *proxy,
    GHashTable *properties,
    const GError *error,
    gpointer user_data,
    GObject *weak_object)
{
  GPtrArray *cert_data;
  EmpathyTLSCertificate *self = EMPATHY_TLS_CERTIFICATE (weak_object);
  EmpathyTLSCertificatePriv *priv = GET_PRIV (self);

  if (error != NULL)
    {
      g_simple_async_result_set_from_error (priv->async_prepare_res, error);
      g_simple_async_result_complete (priv->async_prepare_res);
      tp_clear_object (&priv->async_prepare_res);

      return;
    }

  priv->cert_type = g_strdup (tp_asv_get_string (properties,
          "CertificateType"));
  priv->state = tp_asv_get_uint32 (properties, "State", NULL);

  cert_data = tp_asv_get_boxed (properties, "CertificateChainData",
      TP_ARRAY_TYPE_UCHAR_ARRAY_LIST);
  g_assert (cert_data != NULL);
  priv->cert_data = g_boxed_copy (TP_ARRAY_TYPE_UCHAR_ARRAY_LIST, cert_data);

  DEBUG ("Got a certificate chain long %u, of type %s",
      priv->cert_data->len, priv->cert_type);

  priv->is_prepared = TRUE;

  g_simple_async_result_complete (priv->async_prepare_res);
  tp_clear_object (&priv->async_prepare_res);
}
Example #13
0
static TpBaseConnection *
new_connection (TpBaseProtocol *protocol,
    GHashTable *asv,
    GError **error)
{
  ExampleContactListConnection *conn;
  const gchar *account;
  guint sim_delay;

  account = tp_asv_get_string (asv, "account");
  /* telepathy-glib checked this for us */
  g_assert (account != NULL);

  sim_delay = tp_asv_get_uint32 (asv, "simulation-delay", NULL);

  conn = EXAMPLE_CONTACT_LIST_CONNECTION (
      g_object_new (EXAMPLE_TYPE_CONTACT_LIST_CONNECTION,
        "account", account,
        "protocol", tp_base_protocol_get_name (protocol),
        "simulation-delay", sim_delay,
        NULL));

  return (TpBaseConnection *) conn;
}
static gboolean
rakia_media_manager_requestotron (TpChannelManager *manager,
                                  gpointer request_token,
                                  GHashTable *request_properties,
                                  RequestMethod method)
{
  RakiaMediaManager *self = RAKIA_MEDIA_MANAGER (manager);
  RakiaMediaManagerPrivate *priv = RAKIA_MEDIA_MANAGER_GET_PRIVATE (self);
  TpBaseConnection *conn = (TpBaseConnection *) priv->conn;
  TpHandleType handle_type;
  TpHandle handle;
  RakiaSipSession *session;
  RakiaCallChannel *channel = NULL;
  GError *error = NULL;
  GSList *request_tokens;
  gboolean valid = FALSE;
  gboolean initial_audio = FALSE;
  gboolean initial_video = FALSE;
  TpHandle self_handle = tp_base_connection_get_self_handle (conn);

  /* Supported modes of operation:
   * - RequestChannel(Contact, n) where n != 0:
   *     channel has TargetHandle=n;
   *     n is in remote pending;
   *     call is started when caller calls RequestStreams.
   * - CreateChannel({THT: Contact, TH: n}):
   *     channel has TargetHandle=n
   *     n is not in the group interface at all
   *     call is started when caller calls RequestStreams.
   * - EnsureChannel({THT: Contact, TH: n}):
   *     look for a channel whose peer is n, and return that if found with
   *       whatever properties and group membership it has;
   *     otherwise the same as into CreateChannel
   */

  if (tp_strdiff (tp_asv_get_string (request_properties,
          TP_PROP_CHANNEL_CHANNEL_TYPE),
        TP_IFACE_CHANNEL_TYPE_CALL))
    return FALSE;

  if (tp_asv_get_boolean (request_properties,
          TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO, &valid) && valid)
    initial_audio = TRUE;
  if (tp_asv_get_boolean (request_properties,
          TP_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO, &valid) && valid)
    initial_audio = TRUE;

  if (!initial_audio && !initial_video)
    return FALSE;

  handle_type = tp_asv_get_uint32 (request_properties,
      TP_IFACE_CHANNEL ".TargetHandleType", NULL);

  handle = tp_asv_get_uint32 (request_properties,
      TP_IFACE_CHANNEL ".TargetHandle", NULL);

  if (handle_type != TP_HANDLE_TYPE_CONTACT)
    return FALSE;

  g_assert (handle != 0);

  if (tp_channel_manager_asv_has_unknown_properties (request_properties,
          media_channel_fixed_properties, named_channel_allowed_properties,
          &error))
    goto error;

  /* Calls to self are problematic in terms of StreamedMedia channel
   * interface and its semantically required Group member changes;
   * we disable them until a better API is available through
   * Call channel type */
  if (handle == self_handle)
    {
      g_set_error (&error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
          "Cannot call self");
      goto error;
    }

  if (method == METHOD_ENSURE)
    {
      guint i;
      TpHandle peer = 0;

      for (i = 0; i < priv->channels->len; i++)
        {
          channel = g_ptr_array_index (priv->channels, i);
          g_object_get (channel, "peer", &peer, NULL);

          if (peer == handle)
            {
              tp_channel_manager_emit_request_already_satisfied (self,
                  request_token, TP_EXPORTABLE_CHANNEL (channel));
              return TRUE;
            }
        }
    }

  session = new_session (self, NULL, handle);
  channel = new_call_channel (self, self_handle, handle,
      request_properties, session);
  g_object_unref (session);

  request_tokens = g_slist_prepend (NULL, request_token);
  tp_channel_manager_emit_new_channel (self,
      TP_EXPORTABLE_CHANNEL (channel), request_tokens);
  g_slist_free (request_tokens);

  return TRUE;

error:
  tp_channel_manager_emit_request_failed (self, request_token,
      error->domain, error->code, error->message);
  g_error_free (error);
  return TRUE;
}
Example #15
0
void idle_text_send(GObject *obj, TpMessage *message, TpMessageSendingFlags flags, const gchar *recipient, IdleConnection *conn) {
    GError *error = NULL;
    const GHashTable *part;
    TpChannelTextMessageType type = TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL;
    gboolean result = TRUE;
    const gchar *content_type, *text;
    guint n_parts;
    GStrv messages;
    GStrv bodies;
    gsize msg_len;
    guint i;

#define INVALID_ARGUMENT(msg, ...) \
	G_STMT_START { \
		IDLE_DEBUG (msg , ## __VA_ARGS__); \
		g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, \
				msg , ## __VA_ARGS__); \
		goto failed; \
	} G_STMT_END

    g_return_if_fail (recipient != NULL);

    part = tp_message_peek (message, 0);

    if (tp_asv_lookup (part, "message-type") != NULL)
        type = tp_asv_get_uint32 (part, "message-type", &result);

    if (!result)
        INVALID_ARGUMENT ("message-type must be a 32-bit unsigned integer");

    if (type >= NUM_TP_CHANNEL_TEXT_MESSAGE_TYPES)
        INVALID_ARGUMENT ("invalid message type: %u", type);

    n_parts = tp_message_count_parts (message);

    if (n_parts != 2)
        INVALID_ARGUMENT ("message must contain exactly 1 part, not %u", (n_parts - 1));

    part = tp_message_peek (message, 1);
    content_type = tp_asv_get_string (part, "content-type");
    text = tp_asv_get_string (part, "content");

    if (tp_strdiff (content_type, "text/plain"))
        INVALID_ARGUMENT ("message must be text/plain");

    if (tp_str_empty (text))
        INVALID_ARGUMENT ("content must be a UTF-8 string");

    /* Okay, it's valid. Let's send it. */

    msg_len = idle_connection_get_max_message_length(conn);
    messages = idle_text_encode_and_split(type, recipient, text, msg_len, &bodies, &error);
    if (messages == NULL)
        goto failed;

    for(i = 0; messages[i] != NULL; i++) {
        g_assert(bodies[i] != NULL);
        idle_connection_send(conn, messages[i]);
    }

    g_strfreev(messages);
    g_strfreev(bodies);

    tp_message_mixin_sent (obj, message, flags, "", NULL);
    return;

failed:
    g_assert (error != NULL);
    tp_message_mixin_sent (obj, message, 0, NULL, error);
    g_error_free (error);
}
static gboolean
_im_manager_requestotron (IdleIMManager *self,
						  gpointer request_token,
						  GHashTable *request_properties,
						  gboolean require_new)
{
	IdleIMManagerPrivate *priv = IDLE_IM_MANAGER_GET_PRIVATE (self);
	TpBaseConnection *base_conn = (TpBaseConnection *) priv->conn;
	TpHandleRepoIface *contact_repo =
		tp_base_connection_get_handles (base_conn, TP_HANDLE_TYPE_CONTACT);
	TpHandle handle;
	GError *error = NULL;
	TpExportableChannel *channel;

	if (tp_strdiff (tp_asv_get_string (request_properties,
									   TP_IFACE_CHANNEL ".ChannelType"), TP_IFACE_CHANNEL_TYPE_TEXT))
		return FALSE;

	if (tp_asv_get_uint32 (request_properties,
						   TP_IFACE_CHANNEL ".TargetHandleType", NULL) != TP_HANDLE_TYPE_CONTACT)
		return FALSE;

	handle = tp_asv_get_uint32 (request_properties,
								TP_IFACE_CHANNEL ".TargetHandle", NULL);

	if (!tp_handle_is_valid (contact_repo, handle, &error))
		goto error;

	/* Check if there are any other properties that we don't understand */
	if (tp_channel_manager_asv_has_unknown_properties (request_properties,
													   im_channel_fixed_properties,
													   im_channel_allowed_properties,
													   &error))
	{
		goto error;
	}

	/* Don't support opening a channel to our self handle */
	if (handle == base_conn->self_handle)
	{
		g_set_error (&error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
					 "Can't open a text channel to yourself");
		goto error;
	}

	channel = g_hash_table_lookup (priv->channels, GUINT_TO_POINTER (handle));

	if (channel == NULL)
	{
		_im_manager_new_channel (self, handle, base_conn->self_handle, request_token);
		return TRUE;
	}

	if (require_new)
	{
		g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
					 "Already chatting with contact #%u in another channel", handle);
		goto error;
	}

	tp_channel_manager_emit_request_already_satisfied (self, request_token,
													   channel);
	return TRUE;

error:
	tp_channel_manager_emit_request_failed (self, request_token,
											error->domain, error->code, error->message);
	g_error_free (error);
	return TRUE;
}
static gboolean
ring_media_requestotron(RingMediaManager *self,
  gpointer request,
  GHashTable *properties,
  RequestotronMethod kind)
{
  RingMediaManagerPrivate *priv = self->priv;
  TpHandle handle;

  /* If we're not connected, calls aren't supported. */
  if (self->priv->call_service == NULL)
    return FALSE;

  handle = tp_asv_get_uint32 (properties,
      TP_IFACE_CHANNEL ".TargetHandle", NULL);

  if (kind == METHOD_COMPATIBLE &&
    handle == 0 &&
    ring_properties_satisfy(properties,
      ring_anon_channel_fixed_properties(),
      ring_anon_channel_allowed_properties)) {
    return ring_media_manager_outgoing_call(self, request, 0, 0, NULL, FALSE);
  }

  if (tp_asv_get_initial_video (properties, FALSE))
    {
      tp_channel_manager_emit_request_failed (self, request,
          TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
          "Video calls are not supported");
      return TRUE;
    }

  if (handle != 0 &&
    ring_properties_satisfy(properties,
      ring_call_channel_fixed_properties(),
      ring_call_channel_allowed_properties)) {
    RingCallChannel *channel;
    char const *target_id;
    GError *error = NULL;

    target_id = ring_connection_inspect_contact(priv->connection, handle);

    if (!modem_call_validate_address(target_id, &error)) {
      tp_channel_manager_emit_request_failed(
        self, request, TP_ERRORS, TP_ERROR_INVALID_HANDLE, error->message);
      g_error_free(error);
      return TRUE;
    }
    /* We do not yet support 'w' */
    else if (strchr(target_id, 'w')) {
      tp_channel_manager_emit_request_failed(
        self, request,
        TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
        "Dial strings containing 'w' are not supported");
      return TRUE;
    }

    if (kind == METHOD_ENSURE) {
      channel = ring_media_manager_lookup_by_peer(self, handle);
      if (channel) {
        tp_channel_manager_emit_request_already_satisfied(
          self, request, TP_EXPORTABLE_CHANNEL(channel));
        return TRUE;
      }
    }

    return ring_media_manager_outgoing_call(self, request,
      handle,
      kind == METHOD_COMPATIBLE ? handle : 0,
      modem_call_get_emergency_service(priv->call_service, target_id),
      tp_asv_get_initial_audio(properties, FALSE));
  }

  return FALSE;
}
static gboolean
set_content_hash_type_from_classes (EmpathyFTHandler *handler,
    GPtrArray *classes)
{
  GArray *possible_values;
  guint value;
  gboolean valid;
  EmpathyFTHandlerPriv *priv = GET_PRIV (handler);
  gboolean support_ft = FALSE;
  guint i;

  possible_values = g_array_new (TRUE, TRUE, sizeof (guint));

  for (i = 0; i < classes->len; i++)
    {
      GHashTable *fixed;
      GStrv allowed;
      const gchar *chan_type;

      tp_value_array_unpack (g_ptr_array_index (classes, i), 2,
          &fixed, &allowed);

      chan_type = tp_asv_get_string (fixed, TP_PROP_CHANNEL_CHANNEL_TYPE);

      if (tp_strdiff (chan_type, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER))
        continue;

      if (tp_asv_get_uint32 (fixed, TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, NULL) !=
          TP_HANDLE_TYPE_CONTACT)
        continue;

      support_ft = TRUE;

      value = tp_asv_get_uint32
        (fixed, TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_CONTENT_HASH_TYPE,
         &valid);

      if (valid)
        g_array_append_val (possible_values, value);
    }

  if (!support_ft)
    {
      g_array_free (possible_values, TRUE);
      return FALSE;
    }

  if (possible_values->len == 0)
    {
      /* there are no channel classes with hash support, disable it. */
      priv->use_hash = FALSE;
      priv->content_hash_type = TP_FILE_HASH_TYPE_NONE;

      goto out;
    }

  priv->use_hash = TRUE;

  if (possible_values->len == 1)
    {
      priv->content_hash_type = g_array_index (possible_values, guint, 0);
    }
  else
    {
      /* order the array and pick the first non zero, so that MD5
       * is the preferred value.
       */
      g_array_sort (possible_values, empathy_uint_compare);

      if (g_array_index (possible_values, guint, 0) == 0)
        priv->content_hash_type = g_array_index (possible_values, guint, 1);
      else
        priv->content_hash_type = g_array_index (possible_values, guint, 0);
    }

out:
  g_array_free (possible_values, TRUE);

  DEBUG ("Hash enabled %s; setting content hash type as %u",
         priv->use_hash ? "True" : "False", priv->content_hash_type);

  return TRUE;
}
static void
on_call_channel_get_all_properties_cb (TpProxy *proxy,
    GHashTable *properties,
    const GError *error,
    gpointer user_data,
    GObject *weak_object)
{
  TpyCallChannel *self = TPY_CALL_CHANNEL (proxy);
  GSimpleAsyncResult *result = user_data;
  GHashTable *hash_table;
  GPtrArray *contents;
  guint i;

  if (error != NULL)
    {
      g_warning ("Could not get the channel properties: %s", error->message);
      g_simple_async_result_set_from_error (result, error);
      goto out;
    }

  self->priv->state = tp_asv_get_uint32 (properties,
      "CallState", NULL);
  self->priv->flags = tp_asv_get_uint32 (properties,
      "CallFlags", NULL);
  self->priv->initial_audio = tp_asv_get_boolean (properties,
      "InitialAudio", NULL);
  self->priv->initial_video = tp_asv_get_boolean (properties,
      "InitialVideo", NULL);

  hash_table = tp_asv_get_boxed (properties,
      "CallStateDetails", TP_HASH_TYPE_STRING_VARIANT_MAP);
  if (hash_table != NULL)
    self->priv->details = g_boxed_copy (TP_HASH_TYPE_STRING_VARIANT_MAP,
        hash_table);

  hash_table = tp_asv_get_boxed (properties,
      "CallMembers", TPY_HASH_TYPE_CALL_MEMBER_MAP);
  update_call_members (self, hash_table, NULL);

  contents = tp_asv_get_boxed (properties,
      "Contents", TP_ARRAY_TYPE_OBJECT_PATH_LIST);

  for (i = 0; i < contents->len; i++)
    {
      const gchar *content_path = g_ptr_array_index (contents, i);
      TpyCallContent *content;

      DEBUG ("Content added: %s", content_path);

      content = g_object_new (TPY_TYPE_CALL_CONTENT,
              "bus-name", tp_proxy_get_bus_name (self),
              "dbus-daemon", tp_proxy_get_dbus_daemon (self),
              "dbus-connection", tp_proxy_get_dbus_connection (self),
              "object-path", content_path,
              NULL);

      if (content == NULL)
        {
          g_warning ("Could not create a CallContent for path %s", content_path);

          g_simple_async_result_set_error (result, TP_ERRORS, TP_ERROR_CONFUSED,
              "Could not create a CallContent for path %s", content_path);
          goto out;
        }

      g_ptr_array_add (self->priv->contents, content);

      tp_g_signal_connect_object (content, "notify::ready",
        G_CALLBACK (on_content_ready_cb), self, 0);
    }

  g_signal_emit (self, _signals[MEMBERS_CHANGED], 0, self->priv->members);

  self->priv->properties_retrieved = TRUE;

  maybe_go_to_ready (self);

out:
  /* TODO; ideally we should get rid of the ready property and complete once
   * all the contents have been prepared. Or maybe that should be another
   * feature? */
  g_simple_async_result_complete (result);
}