static void
ringing_cb (RakiaSipSession *session, RakiaCallChannel *self)
{

  tp_base_call_channel_update_member_flags (TP_BASE_CALL_CHANNEL (self),
      tp_base_channel_get_target_handle (TP_BASE_CHANNEL (self)),
      TP_CALL_MEMBER_FLAG_RINGING,
      tp_base_channel_get_target_handle (TP_BASE_CHANNEL (self)),
      TP_CALL_STATE_CHANGE_REASON_PROGRESS_MADE,
      "", "Remote side has started ringing");
}
Ejemplo n.º 2
0
    static void
send_message (GObject *object,
        TpMessage *message,
        TpMessageSendingFlags flags)
{
    FetionImChannel *self = FETION_IM_CHANNEL (object);
    TpBaseChannel *base = TP_BASE_CHANNEL (self);
    if (tp_asv_get_string (tp_message_peek (message, 0), "interface") != NULL)
    {
        /* this message is interface-specific - let's not echo it */
        goto finally;
    }

    FetionConnection *conn =
        FETION_CONNECTION (tp_base_channel_get_connection(base));

    HybridAccount *account = conn->priv->account;

    TpHandle from = tp_base_channel_get_target_handle (base);
    const GHashTable *input = tp_message_peek (message, 1);
    const gchar *send_message = tp_asv_get_string (input, "content");
    HybridBuddy *buddy = hybrid_blist_find_buddy_by_handle(account, from);
    hybrid_conv_send_message(account,buddy,send_message);

finally:
    /* "OK, we've sent the message" (after calling this, message must not be
     * dereferenced) */
    tp_message_mixin_sent (object, message, flags, "", NULL);

}
static void
_im_channel_closed_cb (IdleIMChannel *chan,
					  gpointer user_data)
{
	IdleIMManager *self = IDLE_IM_MANAGER (user_data);
	IdleIMManagerPrivate *priv = IDLE_IM_MANAGER_GET_PRIVATE (self);
	TpBaseChannel *base = TP_BASE_CHANNEL (chan);

	tp_channel_manager_emit_channel_closed_for_object (self,
													   TP_EXPORTABLE_CHANNEL (chan));

	if (priv->channels)
	{
		TpHandle handle = tp_base_channel_get_target_handle (base);

		if (tp_base_channel_is_destroyed (base))
		{
			IDLE_DEBUG ("removing channel with handle %u", handle);
			g_hash_table_remove (priv->channels, GUINT_TO_POINTER (handle));
		} else {
			IDLE_DEBUG ("reopening channel with handle %u due to pending messages",
				handle);
			tp_channel_manager_emit_new_channel (self,
				(TpExportableChannel *) chan, NULL);
		}
	}
}
static void
remote_held_changed_cb (RakiaSipSession *session, GParamSpec *pspec,
    RakiaCallChannel *self)
{
  TpBaseChannel *bchan = TP_BASE_CHANNEL (self);
  TpBaseCallChannel *bcc = TP_BASE_CALL_CHANNEL (self);
  gboolean remote_held;
  GHashTable *members;
  TpCallMemberFlags member_flags;
  TpHandle remote_contact = tp_base_channel_get_target_handle (bchan);

  g_object_get (session, "remote-held", &remote_held, NULL);

  members = tp_base_call_channel_get_call_members (bcc);

  member_flags = GPOINTER_TO_UINT (g_hash_table_lookup (members,
          GUINT_TO_POINTER (remote_contact)));

  if (!!(member_flags & TP_CALL_MEMBER_FLAG_HELD) == remote_held)
    return;

  if (remote_held)
    member_flags |= TP_CALL_MEMBER_FLAG_HELD;
  else
    member_flags &= ~TP_CALL_MEMBER_FLAG_HELD;

  tp_base_call_channel_update_member_flags (bcc, remote_contact, member_flags,
      remote_contact, TP_CALL_STATE_CHANGE_REASON_USER_REQUESTED, "",
      remote_held ? "Held by remote side" : "Unheld by remote side");
}
static void
new_content (RakiaCallChannel *self,
    const gchar *name,
    RakiaSipMedia *media,
    TpCallContentDisposition disposition)
{
  TpBaseChannel *bchan = TP_BASE_CHANNEL (self);
  RakiaCallContent *content;
  TpMediaStreamType media_type;
  TpHandle creator;
  gchar *object_path;
  gchar *free_name = NULL;
  const gchar *media_type_name;

  switch (rakia_sip_media_get_media_type (media))
    {
    case TP_MEDIA_STREAM_TYPE_AUDIO:
      media_type = TP_MEDIA_STREAM_TYPE_AUDIO;
      media_type_name = "Audio";
      break;
    case TP_MEDIA_STREAM_TYPE_VIDEO:
      media_type = TP_MEDIA_STREAM_TYPE_VIDEO;
      media_type_name = "Video";
      break;
    default:
      g_assert_not_reached ();
    }

  if (rakia_sip_media_is_created_locally (media))
    creator = tp_base_channel_get_self_handle (bchan);
  else
    creator = tp_base_channel_get_target_handle (bchan);

  object_path = g_strdup_printf ("%s/Content%u",
      tp_base_channel_get_object_path (bchan), ++self->priv->last_content_no);

  if (name == NULL)
    name = free_name = g_strdup_printf ("%s %u", media_type_name,
        self->priv->last_content_no);

  /* We already request bidi for initial media,
   * the client can change it before accepting.
   */
  if (disposition == TP_CALL_CONTENT_DISPOSITION_INITIAL)
    rakia_sip_media_set_requested_direction (media,
        TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL);


  content = rakia_call_content_new (self, media, object_path,
      tp_base_channel_get_connection (bchan), name,
      media_type, creator, disposition);

  g_free (free_name);
  g_free (object_path);

  tp_base_call_channel_add_content (TP_BASE_CALL_CHANNEL (self),
      TP_BASE_CALL_CONTENT (content));

  rakia_call_content_add_stream (content);
}
Ejemplo n.º 6
0
/** start send message **/
static void
send_message (GObject *object,
        TpMessage *message,
        TpMessageSendingFlags flags)
{
    LwqqChannel* self = LWQQ_CHANNEL(object);
    TpBaseChannel *base = TP_BASE_CHANNEL (self);
    if (tp_asv_get_string (tp_message_peek (message, 0), "interface") != NULL)
    {
        /* this message is interface-specific - let's not echo it */
        goto finally;
    }

    LwqqConnection *conn =
        LWQQ_CONNECTION(tp_base_channel_get_connection(base));

    LwqqClient* lc = conn->lc;

    TpHandle to = tp_base_channel_get_target_handle (base);
    const GHashTable *input = tp_message_peek (message, 1);
    const gchar *send_message = tp_asv_get_string (input, "content");
    LwqqBuddy* buddy = lwqq_find_buddy_by_handle(conn, to);
    lwqq_msg_send_text(lc, LWQQ_MS_BUDDY_MSG, buddy->uin, send_message);

finally:
    /* "OK, we've sent the message" (after calling this, message must not be
* dereferenced) */
    tp_message_mixin_sent (object, message, flags, "", NULL);
}
static void
media_remote_codecs_updated_cb (RakiaSipMedia *media, gboolean is_offer,
    RakiaCallContent *self)
{
  TpBaseCallContent *bcc = TP_BASE_CALL_CONTENT (self);
  TpBaseMediaCallContent *bmcc = TP_BASE_MEDIA_CALL_CONTENT (self);
  RakiaCallContentPrivate *priv = self->priv;
  GPtrArray *remote_codecs =
      rakia_sip_media_get_remote_codec_offer (priv->media);
  TpCallContentMediaDescription *md;
  TpDBusDaemon *bus = tp_base_connection_get_dbus_daemon (
      tp_base_call_content_get_connection (bcc));
  gchar *object_path;
  guint i, j;

  if (remote_codecs == NULL)
    return;

  object_path = g_strdup_printf ("%s/Offer%u",
      tp_base_call_content_get_object_path (bcc), ++priv->codec_offer_id);

  md = tp_call_content_media_description_new (bus, object_path,
      tp_base_channel_get_target_handle (TP_BASE_CHANNEL (priv->channel)),
      TRUE, is_offer);

  g_free (object_path);

  for (i = 0; i < remote_codecs->len; i++)
    {
      RakiaSipCodec *codec = g_ptr_array_index (remote_codecs, i);
      GHashTable *parameters = g_hash_table_new (g_str_hash, g_str_equal);

      /* No need to copy the values as .._append_codec() will */
      if (codec->params)
        for (j = 0; j < codec->params->len; j++)
          {
            RakiaSipCodecParam *param = g_ptr_array_index (codec->params, j);

            g_hash_table_insert (parameters, param->name, param->value);
          }

      tp_call_content_media_description_append_codec (md, codec->id,
          codec->encoding_name, codec->clock_rate, codec->channels, TRUE,
          parameters);

      g_hash_table_unref (parameters);
    }

  tp_base_media_call_content_offer_media_description_async (bmcc,
      md, md_offer_cb, GUINT_TO_POINTER (FALSE));

  g_object_unref (md);
}
Ejemplo n.º 8
0
gboolean
gabble_call_member_start_session (GabbleCallMember *self,
    const gchar *audio_name,
    const gchar *video_name,
    GError **error)
{
  GabbleCallMemberPrivate *priv = self->priv;
  TpBaseChannel *base_channel = TP_BASE_CHANNEL (priv->call);
  TpHandle target = tp_base_channel_get_target_handle (base_channel);
  const gchar *resource;
  JingleDialect dialect;
  gchar *jid;
  const gchar *transport;
  GabbleJingleFactory *jf;
  GabbleJingleSession *session;

  /* FIXME might need to wait on capabilities, also don't need transport
   * and dialect already */
  if (!jingle_pick_best_resource (gabble_call_member_get_connection (self),
          target, audio_name != NULL, video_name != NULL,
          &transport, &dialect, &resource))
    {
      g_set_error (error, TP_ERROR, TP_ERROR_NOT_CAPABLE,
        "member does not have the desired audio/video capabilities");
      return FALSE;
    }

  jid = gabble_peer_to_jid (gabble_call_member_get_connection (self), target, resource);

  jf = gabble_jingle_mint_get_factory (
        gabble_call_member_get_connection (self)->jingle_mint);
  g_return_val_if_fail (jf != NULL, FALSE);

  session = gabble_jingle_factory_create_session (jf, jid, dialect, FALSE);
  g_free (jid);

  gabble_call_member_set_session (self, session);

  priv->transport_ns = g_strdup (transport);

  if (audio_name != NULL)
    gabble_call_member_create_content (self, audio_name,
      JINGLE_MEDIA_TYPE_AUDIO, JINGLE_CONTENT_SENDERS_BOTH, NULL);

  if (video_name != NULL)
    gabble_call_member_create_content (self, video_name,
      JINGLE_MEDIA_TYPE_VIDEO, JINGLE_CONTENT_SENDERS_BOTH, NULL);

  return TRUE;
}
static void
media_removed_cb (RakiaSipSession *session, RakiaSipMedia *media,
    RakiaCallChannel *self)
{
  RakiaCallContent *content;

  content = rakia_call_channel_get_content_by_media (self, media);
  if (content == NULL)
    return;

  tp_base_call_channel_remove_content (TP_BASE_CALL_CHANNEL (self),
      TP_BASE_CALL_CONTENT (content),
      tp_base_channel_get_target_handle (TP_BASE_CHANNEL (self)),
      TP_CALL_STATE_CHANGE_REASON_USER_REQUESTED, "", "Removed by remote side");
}
static void
rakia_call_content_constructed (GObject *object)
{
  RakiaCallContent *self = RAKIA_CALL_CONTENT (object);
  RakiaCallContentPrivate *priv = self->priv;
  TpBaseChannel *bchan = TP_BASE_CHANNEL (priv->channel);
  TpBaseCallContent *bcc = TP_BASE_CALL_CONTENT (self);
  TpBaseMediaCallContent *bmcc = TP_BASE_MEDIA_CALL_CONTENT (self);
  TpHandle creator;
  gchar *object_path;

  g_signal_connect_object (priv->media, "remote-codec-offer-updated",
      G_CALLBACK (media_remote_codecs_updated_cb), self, 0);

  g_signal_connect (self, "local-media-description-updated",
      G_CALLBACK (local_media_description_updated), NULL);

  g_object_get (object, "creator", &creator, NULL);

  if (creator == tp_base_channel_get_self_handle (bchan))
    {
      TpCallContentMediaDescription *md;
      TpDBusDaemon *bus = tp_base_connection_get_dbus_daemon (
          tp_base_call_content_get_connection (bcc));

      object_path = g_strdup_printf ("%s/InitialOffer",
          tp_base_call_content_get_object_path (bcc));

      md = tp_call_content_media_description_new (bus, object_path,
          tp_base_channel_get_target_handle (bchan), FALSE, TRUE);
      g_free (object_path);

      tp_base_media_call_content_offer_media_description_async (bmcc,
          md, md_offer_cb, GUINT_TO_POINTER (TRUE));
    }
  else
    {
      media_remote_codecs_updated_cb (priv->media, TRUE, self);
    }

  G_OBJECT_CLASS (rakia_call_content_parent_class)->constructed (object);
}
Ejemplo n.º 11
0
/**
 * im_channel_closed_cb:
 *
 * Signal callback for when an IM channel is closed. Removes the references
 * that #GabbleConnection holds to them - unless the channel has pending
 * messages, in which case it is re-announced (so from the perspective of the
 * D-Bus API, it was replaced by an identical channel).
 */
static void
im_channel_closed_cb (GabbleIMChannel *chan, gpointer user_data)
{
  GabbleImFactory *self = GABBLE_IM_FACTORY (user_data);
  GabbleImFactoryPrivate *priv = self->priv;
  TpBaseChannel *base = TP_BASE_CHANNEL (chan);
  TpHandle contact_handle = tp_base_channel_get_target_handle (base);

  DEBUG ("%p, channel %p", self, chan);

  if (tp_base_channel_is_registered (base))
    {
      tp_channel_manager_emit_channel_closed_for_object (self,
          (TpExportableChannel *) chan);
    }

  if (priv->channels != NULL)
    {
      if (tp_base_channel_is_destroyed (base))
        {
          DEBUG ("removing channel with handle %u", contact_handle);
          g_hash_table_remove (priv->channels,
              GUINT_TO_POINTER (contact_handle));
        }
      else if (tp_base_channel_is_respawning (base))
        {
          DEBUG ("reopening channel with handle %u due to pending messages",
              contact_handle);
          tp_channel_manager_emit_new_channel (self,
              (TpExportableChannel *) chan, NULL);
        }
      else
        {
          /* this basically means tp_base_channel_disappear() must
           * have been called; this doesn't have any meaning in this
           * channel manager. */
          g_assert_not_reached ();
        }
    }
}
static void
md_offer_cb (GObject *obj, GAsyncResult *res, gpointer user_data)
{
  RakiaCallContent *self = RAKIA_CALL_CONTENT (obj);
  RakiaCallContentPrivate *priv = self->priv;
  TpBaseMediaCallContent *bmcc = TP_BASE_MEDIA_CALL_CONTENT (self);
  GError *error = NULL;
  gboolean is_initial_offer = GPOINTER_TO_UINT (user_data);

  if (tp_base_media_call_content_offer_media_description_finish (bmcc,
          res, &error))
    {
      GHashTable *local_md =
          tp_base_media_call_content_get_local_media_description (bmcc,
              tp_base_channel_get_target_handle (TP_BASE_CHANNEL (priv->channel)));

      set_telepathy_codecs (self, local_md);
    }
  else
    {
      /* Only reject if the codecs where rejected */
      if (error->domain == TP_ERROR &&
          error->code == TP_ERROR_MEDIA_CODECS_INCOMPATIBLE)
        {
          g_assert (!is_initial_offer);

          rakia_sip_media_codecs_rejected (priv->media);

          DEBUG ("Codecs rejected: %s", error->message);

        }

      /* FIXME: We need to allow for partial failures */
      g_clear_error (&error);
    }
}
static void
ended_cb (RakiaSipSession *session, gboolean self_actor, guint status,
    gchar *message, RakiaCallChannel *self)
{
  TpHandle actor;
  TpCallStateChangeReason reason;
  const gchar *detailed_reason = "";
  gchar *free_message = NULL;

  if (self_actor)
    actor = tp_base_channel_get_self_handle (TP_BASE_CHANNEL (self));
  else
    actor = tp_base_channel_get_target_handle (TP_BASE_CHANNEL (self));

  switch (status)
    {
    case 400: /* Bad Request */
    case 405: /* Method Not Allowed */
    case 406: /* Not Acceptable */
    case 413: /* Request Entity Too Large */
    case 414: /* Request-URI Too Long */
    case 415: /* Unsupported Media Type */
    case 416: /* Unsupported URI Scheme */
    case 420: /* Bad Extension */
    case 421: /* Extension Required */
    case 483: /* Too Many Hops */
    case 484: /* Address incomplete */
    case 485: /* Ambiguous */
    case 493: /* Undecipherable */
    case 606: /* Not Acceptable */
      reason = TP_CALL_STATE_CHANGE_REASON_INTERNAL_ERROR;
      detailed_reason = TP_ERROR_STR_CONFUSED;
      break;
    case 500: /* Server Internal Error */
    case 501: /* Not Implemented */
    case 502: /* Bad Gateway */
    case 503: /* Service Unavailable */
    case 504: /* Server Time-out */
    case 505: /* Version Not Supported */
    case 513: /* Message Too Large */
      reason = TP_CALL_STATE_CHANGE_REASON_SERVICE_ERROR;
      detailed_reason = TP_ERROR_STR_SERVICE_CONFUSED;
      break;
    case 401: /* Unauthorized */
    case 403: /* Forbidden */
      reason = TP_CALL_STATE_CHANGE_REASON_PERMISSION_DENIED;
      detailed_reason = TP_ERROR_STR_PERMISSION_DENIED;
      break;
    case 404: /* Not Found */
    case 410: /* Gone */
    case 604: /* Does Not Exist Anywhere */
      reason = TP_CALL_STATE_CHANGE_REASON_INVALID_CONTACT;
      detailed_reason = TP_ERROR_STR_DOES_NOT_EXIST;
      break;
    case 480: /* Temporarily Unavaible */
    case 408: /* Request Timeout */
      reason = TP_CALL_STATE_CHANGE_REASON_NO_ANSWER;
      detailed_reason = TP_ERROR_STR_NO_ANSWER;
      break;
    case 486: /* Busy Here */
    case 600: /* Busy Everywhere */
      reason = TP_CALL_STATE_CHANGE_REASON_BUSY;
      detailed_reason = TP_ERROR_STR_BUSY;
      break;
    case 603: /* Decline */
      reason = TP_CALL_STATE_CHANGE_REASON_REJECTED;
      detailed_reason = TP_ERROR_STR_REJECTED;
      break;

    default:
      reason = TP_CALL_STATE_CHANGE_REASON_USER_REQUESTED;
      break;
    }

  if (message[0] == 0 && reason != 0)
    free_message = message = g_strdup_printf ("SIP status code %d", status);

  tp_base_call_channel_set_state (TP_BASE_CALL_CHANNEL (self),
      TP_CALL_STATE_ENDED, actor, reason, detailed_reason, message);
  g_free (free_message);
}
static void
rakia_call_channel_constructed (GObject *obj)
{
  TpBaseChannel *bc = TP_BASE_CHANNEL (obj);
  TpBaseCallChannel *bcc = TP_BASE_CALL_CHANNEL (obj);
  RakiaCallChannel *self = RAKIA_CALL_CHANNEL (obj);
  GObjectClass *parent_object_class =
      G_OBJECT_CLASS (rakia_call_channel_parent_class);
  TpHandle actor;
  TpCallStateChangeReason reason;

  g_signal_connect_object (self->priv->session, "ended",
      G_CALLBACK (ended_cb), self, 0);
  g_signal_connect_object (self->priv->session, "ringing",
      G_CALLBACK (ringing_cb), self, 0);
  g_signal_connect_object (self->priv->session, "queued",
      G_CALLBACK (queued_cb), self, 0);
  g_signal_connect_object (self->priv->session, "in-progress",
      G_CALLBACK (in_progress_cb), self, 0);
  g_signal_connect_object (self->priv->session, "media-added",
      G_CALLBACK (media_added_cb), self, 0);
  g_signal_connect_object (self->priv->session, "media-removed",
      G_CALLBACK (media_removed_cb), self, 0);
  g_signal_connect_object (self->priv->session, "state-changed",
      G_CALLBACK (state_changed_cb), self, 0);
  g_signal_connect_object (self->priv->session, "notify::remote-held",
      G_CALLBACK (remote_held_changed_cb), self, 0);

  if (tp_base_channel_is_requested (bc))
    {
      const gchar *initial_audio_name;
      const gchar *initial_video_name;

      if (tp_base_call_channel_has_initial_audio (bcc, &initial_audio_name))
        rakia_sip_session_add_media (self->priv->session,
            TP_MEDIA_STREAM_TYPE_AUDIO, initial_audio_name,
            TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL);

      if (tp_base_call_channel_has_initial_video (bcc, &initial_video_name))
        rakia_sip_session_add_media (self->priv->session,
            TP_MEDIA_STREAM_TYPE_VIDEO, initial_video_name,
            TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL);

      actor = tp_base_channel_get_self_handle (bc);
      reason = TP_CALL_STATE_CHANGE_REASON_USER_REQUESTED;
    }
  else
    {
      guint i;
      GPtrArray *medias = rakia_sip_session_get_medias (self->priv->session);

      for (i = 0; i < medias->len; i++)
        {
          RakiaSipMedia *media = g_ptr_array_index (medias, i);
          gchar *name;

          if (media)
            {
              name = g_strdup_printf ("initial_%s_%u",
                  sip_media_get_media_type_str (media), i + 1);
              new_content (self, name, media,
                  TP_CALL_CONTENT_DISPOSITION_INITIAL);
              g_free (name);
            }
        }


      actor = tp_base_channel_get_target_handle (bc);
      reason = TP_CALL_STATE_CHANGE_REASON_PROGRESS_MADE;
    }

  tp_base_call_channel_update_member_flags (bcc,
      tp_base_channel_get_target_handle (bc), 0,
      actor, reason, "", "Call Created");

  if (parent_object_class->constructed != NULL)
    parent_object_class->constructed (obj);
}