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");
}
static gboolean
tp_base_media_call_stream_request_receiving (TpBaseCallStream *bcs,
    TpHandle contact,
    gboolean receive,
    GError **error)
{
  TpBaseMediaCallStream *self = TP_BASE_MEDIA_CALL_STREAM (bcs);
  TpBaseMediaCallStreamClass *klass =
      TP_BASE_MEDIA_CALL_STREAM_GET_CLASS (self);
  TpBaseCallChannel *channel = _tp_base_call_stream_get_channel (bcs);

  if (receive)
    {
      tp_base_call_stream_update_remote_sending_state (bcs, contact,
          TP_SENDING_STATE_PENDING_SEND,
          tp_base_channel_get_self_handle (TP_BASE_CHANNEL (channel)),
          TP_CALL_STATE_CHANGE_REASON_USER_REQUESTED, "",
          "User asked the remote side to start sending");

      if (self->priv->receiving_state == TP_STREAM_FLOW_STATE_STARTED)
        {
          if (klass->request_receiving != NULL)
            {
              klass->request_receiving (self, contact, TRUE);
              return TRUE;
            }
        }

      tp_intset_add (self->priv->receiving_requests, contact);

      tp_base_media_call_stream_update_receiving_state (self);
    }
  else
    {
      tp_base_call_stream_update_remote_sending_state (bcs, contact,
          TP_SENDING_STATE_PENDING_STOP_SENDING,
          tp_base_channel_get_self_handle (TP_BASE_CHANNEL (channel)),
          TP_CALL_STATE_CHANGE_REASON_USER_REQUESTED, "",
          "User asked the remote side to stop sending");

      tp_intset_remove (self->priv->receiving_requests, contact);

      if (klass->request_receiving != NULL)
        klass->request_receiving (self, contact, FALSE);
    }

  return TRUE;
}
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");
}
Ejemplo n.º 4
0
GabbleConnection *
gabble_call_member_get_connection (GabbleCallMember *self)
{
  TpBaseChannel *base_chan = TP_BASE_CHANNEL (self->priv->call);

  return GABBLE_CONNECTION (tp_base_channel_get_connection (base_chan));
}
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
    static GObject *
constructor (GType type,
        guint n_props,
        GObjectConstructParam *props)
{
    GObject *object =
        G_OBJECT_CLASS (fetion_im_channel_parent_class)->constructor (type,
                n_props, props);
    FetionImChannel *self = FETION_IM_CHANNEL (object);
    TpBaseChannel *base = TP_BASE_CHANNEL (self);

    static TpChannelTextMessageType const types[] = {
        TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
        TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION,
        TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE
    };
    static const char * const content_types[] = { "text/plain", NULL };

    tp_base_channel_register (base);

    tp_message_mixin_init (object, G_STRUCT_OFFSET (FetionImChannel, text),
            tp_base_channel_get_connection (base));

    tp_message_mixin_implement_sending (object, send_message,
            G_N_ELEMENTS (types), types,0,
            TP_DELIVERY_REPORTING_SUPPORT_FLAG_RECEIVE_FAILURES,
            content_types);

    return object;
}
Ejemplo n.º 7
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);

}
Ejemplo n.º 8
0
static void
lwqq_channel_init (LwqqChannel *self)
{
   LwqqChannelPrivate *priv;

   priv = LWQQ_CHANNEL_GET_PRIVATE (self);
   self->priv = priv;

   TpBaseChannel* base = TP_BASE_CHANNEL(self);
   GObject* obj = G_OBJECT(self);

   static TpChannelTextMessageType const types[] = {
      TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL
   };

   static const char* const content_types[] = {"text/plain", NULL};

   tp_base_channel_register(base);

   tp_message_mixin_init(G_OBJECT(self), G_STRUCT_OFFSET(LwqqChannel, text),
         tp_base_channel_get_connection(base));

   tp_message_mixin_implement_sending(obj, send_message, G_N_ELEMENTS(types),
         types, 0, TP_DELIVERY_REPORTING_SUPPORT_FLAG_RECEIVE_FAILURES,
         content_types);
}
Ejemplo n.º 9
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);
}
Ejemplo n.º 10
0
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);
		}
	}
}
Ejemplo n.º 11
0
/**
 * tp_base_call_stream_update_remote_sending_state:
 * @self: a #TpBaseCallStream
 * @contact: the #TpHandle to update or add to members
 * @new_state: the new sending state of @contact
 * @actor_handle: the contact responsible for the change, or 0 if no contact was
 *  responsible.
 * @reason: the #TpCallStateChangeReason of the change
 * @dbus_reason: a specific reason for the change, which may be a D-Bus error in
 *  the Telepathy namespace, a D-Bus error in any other namespace (for
 *  implementation-specific errors), or the empty string to indicate that the
 *  state change was not an error.
 * @message: an optional debug message, to expediate debugging the potentially
 *  many processes involved in a call.
 *
 * If @contact is not member, add it. Otherwise update its sending state. Emits
 * RemoteMemberChanged DBus signal if needed.
 *
 * Returns: %TRUE if state was updated, %FALSE if it was already set to
 *  @new_state.
 * Since: 0.17.5
 */
gboolean
tp_base_call_stream_update_remote_sending_state (TpBaseCallStream *self,
    TpHandle contact,
    TpSendingState new_state,
    TpHandle actor_handle,
    TpCallStateChangeReason reason,
    const gchar *dbus_reason,
    const gchar *message)
{
  gpointer old_state_p = NULL;
  TpSendingState old_state;
  gboolean exists;
  GHashTable *updates;
  GHashTable *identifiers;
  GArray *removed_empty;
  GValueArray *reason_array;

  g_return_val_if_fail (TP_IS_BASE_CALL_STREAM (self), FALSE);

  if (new_state == TP_SENDING_STATE_SENDING &&
      self->priv->channel != NULL &&
      tp_base_channel_is_requested (TP_BASE_CHANNEL (self->priv->channel)) &&
      !tp_base_call_channel_is_accepted (self->priv->channel))
    new_state = TP_SENDING_STATE_PENDING_SEND;

  exists = g_hash_table_lookup_extended (self->priv->remote_members,
      GUINT_TO_POINTER (contact), NULL, &old_state_p);
  old_state = GPOINTER_TO_UINT (old_state_p);

  if (exists && old_state == new_state)
    return FALSE;

  DEBUG ("Updating remote member %d state: %d => %d for stream %s",
      contact, old_state, new_state, self->priv->object_path);

  g_hash_table_insert (self->priv->remote_members,
      GUINT_TO_POINTER (contact),
      GUINT_TO_POINTER (new_state));
  g_object_notify (G_OBJECT (self), "remote-members");

  updates = g_hash_table_new (g_direct_hash, g_direct_equal);
  g_hash_table_insert (updates,
      GUINT_TO_POINTER (contact),
      GUINT_TO_POINTER (new_state));
  identifiers = _tp_base_call_dup_member_identifiers (self->priv->conn, updates);
  removed_empty = g_array_new (FALSE, FALSE, sizeof (TpHandle));
  reason_array = _tp_base_call_state_reason_new (actor_handle, reason,
      dbus_reason, message);

  tp_svc_call_stream_emit_remote_members_changed (self, updates, identifiers,
      removed_empty, reason_array);

  g_array_unref (removed_empty);
  tp_value_array_free (reason_array);
  g_hash_table_unref (updates);
  g_hash_table_unref (identifiers);

  return TRUE;
}
Ejemplo n.º 12
0
    static void
destroyable_destroy (TpSvcChannelInterfaceDestroyable *iface,
        DBusGMethodInvocation *context)
{
    TpBaseChannel *self = TP_BASE_CHANNEL (iface);

    tp_message_mixin_clear ((GObject *) self);
    fetion_im_channel_close (self);
    g_assert (tp_base_channel_is_destroyed (self));
    tp_svc_channel_interface_destroyable_return_from_destroy (context);
}
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.º 14
0
static void
tp_tests_room_list_chan_constructed (GObject *object)
{
  TpTestsRoomListChan *self = TP_TESTS_ROOM_LIST_CHAN (object);
  void (*chain_up) (GObject *) =
      ((GObjectClass *) tp_tests_room_list_chan_parent_class)->constructed;

  if (chain_up != NULL)
    chain_up (object);

  tp_base_channel_register (TP_BASE_CHANNEL (self));
}
Ejemplo n.º 15
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;
}
Ejemplo n.º 16
0
void
gabble_server_sasl_channel_start_auth_async (GabbleServerSaslChannel *self,
    GAsyncReadyCallback callback,
    gpointer user_data)
{
  GabbleServerSaslChannelPrivate *priv = self->priv;

  g_assert (priv->result == NULL);
  g_assert (priv->sasl_status == TP_SASL_STATUS_NOT_STARTED);
  DEBUG ("Starting authentication");

  priv->result = g_simple_async_result_new (G_OBJECT (self), callback,
      user_data, gabble_server_sasl_channel_start_auth_async);
  tp_base_channel_register (TP_BASE_CHANNEL (self));
}
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");
}
void
rakia_call_channel_hangup_error (RakiaCallChannel *self,
    TpCallStateChangeReason reason,
    const gchar *dbus_reason,
    const gchar *message)
{
  TpHandle self_handle = tp_base_channel_get_self_handle (
      TP_BASE_CHANNEL (self));

  rakia_call_channel_hangup (TP_BASE_CALL_CHANNEL (self),
      reason, dbus_reason, message);

  tp_base_call_channel_set_state (TP_BASE_CALL_CHANNEL (self),
      TP_CALL_STATE_ENDED, self_handle, reason, dbus_reason, message);
}
Ejemplo n.º 19
0
void
ring_media_manager_emit_new_channel(RingMediaManager *self,
  gpointer request,
  gpointer _channel,
  GError *error)
{
  DEBUG("%s(%p, %p, %p, %p) called", __func__, self, request, _channel, error);

  RingMediaManagerPrivate *priv = RING_MEDIA_MANAGER(self)->priv;
  TpBaseChannel *channel = _channel ? TP_BASE_CHANNEL (_channel) : NULL;
  GSList *requests = request ? g_slist_prepend(NULL, request) : NULL;

  if (error == NULL) {
    char *object_path = NULL;

    g_signal_connect(
      channel, "closed", G_CALLBACK(on_media_channel_closed), self);

    g_object_get(channel, "object-path", &object_path, NULL);

    DEBUG("got new channel %p nick %s type %s",
	  channel, get_nick (channel), G_OBJECT_TYPE_NAME (channel));

    g_hash_table_insert(priv->channels, object_path, channel);

    tp_channel_manager_emit_new_channel(self,
      TP_EXPORTABLE_CHANNEL(channel), requests);

    /* Emit Group and StreamedMedia signals */
    ring_media_channel_emit_initial(RING_MEDIA_CHANNEL (channel));
  }
  else {
    DEBUG("new channel %p nick %s type %s failed with " GERROR_MSG_FMT,
	  channel, get_nick (channel), G_OBJECT_TYPE_NAME (channel),
      GERROR_MSG_CODE(error));

    if (request) {
      tp_channel_manager_emit_request_failed(self,
        request, error->domain, error->code, error->message);
    }
    if (_channel)
      g_object_unref(_channel);
  }

  g_slist_free(requests);
}
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);
}
static void
state_changed_cb (RakiaSipSession *session, RakiaSipSessionState old_state,
    RakiaSipSessionState new_state, RakiaCallChannel *self)
{
  switch (new_state)
    {
    case RAKIA_SIP_SESSION_STATE_INVITE_SENT:
      /* Do nothing.. we don't have a TP state for this */
      break;

    case RAKIA_SIP_SESSION_STATE_INVITE_RECEIVED:
      /* This will never be received here because this is what
       * triggers RakiaMediaManager to create a Channel in the first place
       */
      break;

    case RAKIA_SIP_SESSION_STATE_ACTIVE:

      if (tp_base_channel_is_requested (TP_BASE_CHANNEL (self)))
        {
          GList *e;

          tp_base_call_channel_remote_accept (TP_BASE_CALL_CHANNEL (self));

          for (e = tp_base_call_channel_get_contents (
                  TP_BASE_CALL_CHANNEL (self));
               e != NULL;
               e = e->next)
            {
              RakiaCallContent *content = e->data;
              if (content)
                rakia_call_content_remote_accept (content);
            }
        }

    case RAKIA_SIP_SESSION_STATE_ENDED:
      /* the ended callback is used to get more information */
      break;
    default:
      break;
    }
}
Ejemplo n.º 22
0
static IdleIMChannel *
_im_manager_new_channel (IdleIMManager *mgr,
						 TpHandle handle,
						 TpHandle initiator,
						 gpointer request)
{
	IdleIMManagerPrivate *priv = IDLE_IM_MANAGER_GET_PRIVATE (mgr);
	TpBaseConnection *base_connection = TP_BASE_CONNECTION (priv->conn);
	TpHandleRepoIface *handle_repo =
		tp_base_connection_get_handles (base_connection, TP_HANDLE_TYPE_CONTACT);
	IdleIMChannel *chan;
	const gchar *name;
	GSList *requests = NULL;

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

	name = tp_handle_inspect (handle_repo, handle);
	IDLE_DEBUG ("Requested channel for handle: %u (%s)", handle, name);

	chan = g_object_new (IDLE_TYPE_IM_CHANNEL,
						 "connection", priv->conn,
						 "handle", handle,
						 "initiator-handle", initiator,
						 "requested", handle != initiator,
						 NULL);
	tp_base_channel_register (TP_BASE_CHANNEL (chan));
	g_hash_table_insert (priv->channels, GUINT_TO_POINTER (handle), chan);

	if (request != NULL)
		requests = g_slist_prepend (requests, request);

	tp_channel_manager_emit_new_channel (mgr, TP_EXPORTABLE_CHANNEL (chan),
										 requests);

	g_slist_free (requests);

	g_signal_connect (chan, "closed", G_CALLBACK (_im_channel_closed_cb), mgr);

	return chan;
}
Ejemplo n.º 23
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 ();
        }
    }
}
Ejemplo n.º 24
0
/**
 * tp_base_call_stream_update_local_sending_state:
 * @self: a #TpBaseCallStream
 * @new_state: the new local #TpSendingState
 * @actor_handle: the contact responsible for the change, or 0 if no contact was
 *  responsible.
 * @reason: the #TpCallStateChangeReason of the change
 * @dbus_reason: a specific reason for the change, which may be a D-Bus error in
 *  the Telepathy namespace, a D-Bus error in any other namespace (for
 *  implementation-specific errors), or the empty string to indicate that the
 *  state change was not an error.
 * @message: an optional debug message, to expediate debugging the potentially
 *  many processes involved in a call.
 *
 * Update the local sending state, emitting LocalSendingStateChanged
 * DBus signal if needed.
 *
 * Returns: %TRUE if state was updated, %FALSE if it was already set to
 *  @new_state.
 * Since: 0.17.5
 */
gboolean
tp_base_call_stream_update_local_sending_state (TpBaseCallStream *self,
    TpSendingState new_state,
    TpHandle actor_handle,
    TpCallStateChangeReason reason,
    const gchar *dbus_reason,
    const gchar *message)
{
  GValueArray *reason_array;

  g_return_val_if_fail (TP_IS_BASE_CALL_STREAM (self), FALSE);

  if (new_state == TP_SENDING_STATE_SENDING &&
      self->priv->channel != NULL &&
      !tp_base_call_channel_is_accepted (self->priv->channel) &&
      !tp_base_channel_is_requested (TP_BASE_CHANNEL (self->priv->channel)))
    new_state = TP_SENDING_STATE_PENDING_SEND;

  if (self->priv->local_sending_state == new_state)
    return FALSE;

  DEBUG ("Updating local sending state: %d => %d for stream %s",
      self->priv->local_sending_state, new_state, self->priv->object_path);

  self->priv->local_sending_state = new_state;
  g_object_notify (G_OBJECT (self), "local-sending-state");

  reason_array = _tp_base_call_state_reason_new (actor_handle, reason,
      dbus_reason, message);

  tp_svc_call_stream_emit_local_sending_state_changed (
      TP_SVC_CALL_STREAM (self), new_state, reason_array);

  tp_value_array_free (reason_array);

  return TRUE;
}
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);
    }
}
Ejemplo n.º 26
0
static void
gabble_server_sasl_channel_get_property (GObject *object,
    guint property_id,
    GValue *value,
    GParamSpec *pspec)
{
  TpBaseChannel *channel = TP_BASE_CHANNEL (object);
  GabbleServerSaslChannel *self =
    GABBLE_SERVER_SASL_CHANNEL (object);
  GabbleServerSaslChannelPrivate *priv = self->priv;

  switch (property_id)
    {
    case PROP_SASL_STATUS:
      g_value_set_uint (value, priv->sasl_status);
      break;
    case PROP_SASL_ERROR:
      g_value_set_string (value, priv->sasl_error);
      break;
    case PROP_SASL_ERROR_DETAILS:
      g_value_set_boxed (value, priv->sasl_error_details);
      break;
    case PROP_AUTH_METHOD:
      g_value_set_static_string (value,
          TP_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION);
      break;
    case PROP_AVAILABLE_MECHANISMS:
      g_value_set_boxed (value, priv->available_mechanisms);
      break;
    case PROP_SECURE:
      g_value_set_boolean (value, priv->secure);
      break;
    case PROP_CAN_TRY_AGAIN:
      /* Wocky can't retry SASL authentication (although XMPP can) */
      g_value_set_boolean (value, FALSE);
      break;
    case PROP_HAS_INITIAL_DATA:
      /* Yes, XMPP has "initial data" in its SASL */
      g_value_set_boolean (value, TRUE);
      break;
    case PROP_AUTHORIZATION_IDENTITY:
      /* As per RFC 3920, the authorization identity for c2s connections
       * is the desired JID. We can't use conn_util_get_bare_self_jid at
       * this stage of the connection process, because it hasn't been
       * initialized yet. */
        {
          gchar *jid, *username, *stream_server;

          g_object_get (tp_base_channel_get_connection (channel),
              "username", &username,
              "stream-server", &stream_server,
              NULL);
          jid = g_strconcat (username, "@", stream_server, NULL);
          g_free (username);
          g_free (stream_server);

          g_value_take_string (value, jid);
        }
      break;
    case PROP_DEFAULT_REALM:
      /* Like WockySaslDigestMd5, we use the stream server as the default
       * realm, for interoperability with servers that fail to supply a
       * realm but expect us to have this default. */
      g_object_get_property (
          G_OBJECT (tp_base_channel_get_connection (channel)), "stream-server",
          value);
      break;
    case PROP_DEFAULT_USERNAME:
      /* In practice, XMPP servers normally want us to authenticate as the
       * local-part of the JID. */
      g_object_get_property (
          G_OBJECT (tp_base_channel_get_connection (channel)), "username",
          value);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}
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);
}
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);
}
/**
 * new_call_channel
 *
 * Creates a new empty RakiaCallChannel.
 */
static RakiaCallChannel *
new_call_channel (RakiaMediaManager *fac,
                   TpHandle initiator,
                   TpHandle maybe_peer,
                   GHashTable *request_properties,
                   RakiaSipSession *session)
{
  RakiaMediaManagerPrivate *priv = RAKIA_MEDIA_MANAGER_GET_PRIVATE (fac);
  RakiaCallChannel *chan = NULL;
  gchar *object_path;
  gboolean initial_audio = FALSE;
  gboolean initial_video = FALSE;
  gboolean immutable_streams = FALSE;
  const gchar *dtmf_initial_tones = NULL;
  const gchar *initial_audio_name = NULL;
  const gchar *initial_video_name = NULL;
  TpHandle self_handle = tp_base_connection_get_self_handle (priv->conn);

  g_assert (initiator != 0);

  object_path = g_strdup_printf ("%s/CallChannel%u",
      tp_base_connection_get_object_path (priv->conn), priv->channel_index++);

  DEBUG("channel object path %s", object_path);

  if (request_properties != NULL)
    {
      initial_audio = tp_asv_get_boolean (request_properties,
          TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO, NULL);
      initial_video = tp_asv_get_boolean (request_properties,
          TP_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO, NULL);
      initial_audio_name = tp_asv_get_string (request_properties,
          TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO_NAME);
      initial_video_name = tp_asv_get_string (request_properties,
          TP_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO_NAME);
      dtmf_initial_tones = tp_asv_get_string (request_properties,
          TP_PROP_CHANNEL_INTERFACE_DTMF_INITIAL_TONES);
    }

  g_object_get (priv->conn,
      "immutable-streams", &immutable_streams,
      NULL);

  chan = g_object_new (RAKIA_TYPE_CALL_CHANNEL,
                       "connection", priv->conn,
                       "object-path", object_path,
                       "handle", maybe_peer,
                       "initiator-handle", initiator,
                       "initial-audio", initial_audio,
                       "initial-video", initial_video,
                       "initial-audio-name", initial_audio_name,
                       "initial-video-name", initial_video_name,
                       "initial-transport", TP_STREAM_TRANSPORT_TYPE_RAW_UDP,
                       "mutable-contents", !immutable_streams,
                       "initial-tones", dtmf_initial_tones,
                       "sip-session", session,
                       "stun-server", priv->stun_server ? priv->stun_server :
                       "",
                       "stun-port", priv->stun_port,
                       "requested", (initiator == self_handle),
                       NULL);

  g_free (object_path);


  g_signal_connect (chan, "closed", G_CALLBACK (call_channel_closed_cb), fac);

  g_ptr_array_add (priv->channels, chan);

  tp_base_channel_register (TP_BASE_CHANNEL (chan));

  return chan;
}