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"); }
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); }
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; }
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 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); }
/** 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 _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); } } }
/** * 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; }
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); }
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)); }
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; }
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); }
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; } }
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; }
/** * 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 (); } } }
/** * 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); } }
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; }