static void channel_get_all_properties_cb (TpProxy *proxy, GHashTable *properties, const GError *error, gpointer user_data, GObject *weak_object) { CallbacksData *cb_data = user_data; EmpathyFTHandler *handler = EMPATHY_FT_HANDLER (weak_object); EmpathyFTHandlerPriv *priv = GET_PRIV (handler); TpHandle c_handle; if (error != NULL) { if (!g_cancellable_is_cancelled (priv->cancellable)) g_cancellable_cancel (priv->cancellable); cb_data->callback (handler, (GError *) error, cb_data->user_data); callbacks_data_free (cb_data); return; } priv->total_bytes = g_value_get_uint64 ( g_hash_table_lookup (properties, "Size")); priv->transferred_bytes = g_value_get_uint64 ( g_hash_table_lookup (properties, "TransferredBytes")); priv->filename = g_value_dup_string ( g_hash_table_lookup (properties, "Filename")); priv->content_hash = g_value_dup_string ( g_hash_table_lookup (properties, "ContentHash")); priv->content_hash_type = g_value_get_uint ( g_hash_table_lookup (properties, "ContentHashType")); priv->content_type = g_value_dup_string ( g_hash_table_lookup (properties, "ContentType")); priv->description = g_value_dup_string ( g_hash_table_lookup (properties, "Description")); c_handle = tp_channel_get_handle (TP_CHANNEL (proxy), NULL); empathy_tp_contact_factory_get_from_handle ( tp_channel_borrow_connection (TP_CHANNEL (proxy)), c_handle, contact_factory_contact_cb, cb_data, callbacks_data_free, G_OBJECT (handler)); }
static void handle_dbus_channel(TpSimpleHandler* /*handler*/, TpAccount* /*account*/, TpConnection* /*connection*/, GList* channels, GList* /*requests*/, gint64 /*user_action_time*/, TpHandleChannelsContext* context, gpointer user_data) { UT_DEBUGMSG(("handle_dbus_channel()\n")); TelepathyAccountHandler* pHandler = reinterpret_cast<TelepathyAccountHandler*>(user_data); UT_return_if_fail(pHandler); for (GList* chan = channels; chan; chan = chan->next) { TpChannel* channel = TP_CHANNEL(chan->data); UT_continue_if_fail(channel); UT_DEBUGMSG((">>>>> incoming dbus channel: %s\n", tp_channel_get_identifier(channel))); if (tp_channel_get_channel_type_id(channel) != TP_IFACE_QUARK_CHANNEL_TYPE_DBUS_TUBE) continue; /* accept the channel */ tp_cli_channel_type_dbus_tube_call_accept(channel, -1, TP_SOCKET_ACCESS_CONTROL_LOCALHOST, tube_accept_cb, user_data, NULL, NULL); } tp_handle_channels_context_accept(context); }
static void ft_transfer_state_cb (TpFileTransferChannel *channel, GParamSpec *pspec, EmpathyFTHandler *handler) { EmpathyFTHandlerPriv *priv = handler->priv; TpFileTransferStateChangeReason reason; TpFileTransferState state = tp_file_transfer_channel_get_state ( channel, &reason); (void)pspec; /* suppress unused-parameter warning */ if (state == TP_FILE_TRANSFER_STATE_COMPLETED) { priv->is_completed = TRUE; g_signal_emit (handler, signals[TRANSFER_DONE], 0, channel); tp_channel_close_async (TP_CHANNEL (channel), NULL, NULL); if (empathy_ft_handler_is_incoming (handler) && priv->use_hash) { check_hash_incoming (handler); } } else if (state == TP_FILE_TRANSFER_STATE_CANCELLED) { GError *error = error_from_state_change_reason (reason); emit_error_signal (handler, error); g_clear_error (&error); } }
static void on_call_state_changed_cb (TpCallChannel *call, TpCallState state, TpCallFlags flags, TpCallStateReason *reason, GHashTable *details, EmpathyCallHandler *handler) { EmpathyCallHandlerPriv *priv = handler->priv; /* Clean up the TfChannel before bubbling the state-change signal * further up. This ensures that the conference-removed signal is * emitted before state-changed so that the client gets a chance * to remove the conference from the pipeline before resetting the * pipeline itself. */ if (state == TP_CALL_STATE_ENDED) { tp_channel_close_async (TP_CHANNEL (call), NULL, NULL); priv->accept_when_initialised = FALSE; tp_clear_object (&priv->call); tp_clear_object (&priv->tfchannel); } g_signal_emit (handler, signals[STATE_CHANGED], 0, state, reason->dbus_reason); if (state == TP_CALL_STATE_INITIALISED && priv->accept_when_initialised) { tp_call_channel_accept_async (priv->call, on_call_accepted_cb, NULL); priv->accept_when_initialised = FALSE; } }
static void _offer_with_address (TpStreamTubeChannel *self, GHashTable *params) { GValue *addressv = NULL; GError *error = NULL; addressv = tp_address_variant_from_g_socket_address (self->priv->address, &self->priv->socket_type, &error); if (error != NULL) { operation_failed (self, error); g_clear_error (&error); goto finally; } /* Connect the NewRemoteConnection signal */ tp_cli_channel_type_stream_tube_connect_to_new_remote_connection ( TP_CHANNEL (self), _new_remote_connection, NULL, NULL, G_OBJECT (self), &error); if (error != NULL) { operation_failed (self, error); g_clear_error (&error); goto finally; } g_assert (self->priv->parameters == NULL); if (params != NULL) self->priv->parameters = g_hash_table_ref (params); else self->priv->parameters = tp_asv_new (NULL, NULL); g_object_notify (G_OBJECT (self), "parameters"); g_object_notify (G_OBJECT (self), "parameters-vardict"); /* Call Offer */ tp_cli_channel_type_stream_tube_call_offer (TP_CHANNEL (self), -1, self->priv->socket_type, addressv, self->priv->access_control, self->priv->parameters, _channel_offered, NULL, NULL, G_OBJECT (self)); finally: if (addressv != NULL) tp_g_value_slice_free (addressv); }
static void empathy_call_handler_start_tpfs (EmpathyCallHandler *self) { EmpathyCallHandlerPriv *priv = GET_PRIV (self); tf_channel_new_async (TP_CHANNEL (priv->call), on_tf_channel_ready, self); }
/** * tp_stream_tube_channel_get_service: * @self: a #TpStreamTubeChannel * * Return the #TpStreamTubeChannel:service property * * Returns: (transfer none): the value of #TpStreamTubeChannel:service * * Since: 0.13.2 */ const gchar * tp_stream_tube_channel_get_service (TpStreamTubeChannel *self) { GHashTable *props; props = _tp_channel_get_immutable_properties (TP_CHANNEL (self)); return tp_asv_get_string (props, TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SERVICE); }
static void channel_prepared_cb ( GObject *source, GAsyncResult *result, gpointer user_data) { TpFileTransferChannel *channel = TP_FILE_TRANSFER_CHANNEL (source); CallbacksData *cb_data = user_data; EmpathyFTHandler *handler = cb_data->handler; EmpathyFTHandlerPriv *priv = handler->priv; GHashTable *properties; GError *error = NULL; if (!tp_proxy_prepare_finish (channel, result, &error)) { if (!g_cancellable_is_cancelled (priv->cancellable)) g_cancellable_cancel (priv->cancellable); cb_data->callback (handler, error, cb_data->user_data); g_clear_error (&error); callbacks_data_free (cb_data); return; } #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" properties = tp_channel_borrow_immutable_properties (TP_CHANNEL (channel)); #pragma GCC diagnostic pop priv->content_hash = g_strdup ( tp_asv_get_string (properties, "ContentHash")); priv->content_hash_type = tp_asv_get_uint32 ( properties, "ContentHashType", NULL); priv->contact = g_object_ref (tp_channel_get_target_contact (TP_CHANNEL (channel))); cb_data->callback (handler, NULL, cb_data->user_data); }
static void new_local_connection_identified (TpStreamTubeChannel *self, GSocketConnection *conn, guint connection_id) { TpHandle initiator_handle; TpStreamTubeConnection *tube_conn; TpConnection *connection; GArray *features; tube_conn = _tp_stream_tube_connection_new (conn, self); g_hash_table_insert (self->priv->tube_connections, GUINT_TO_POINTER (connection_id), tube_conn); g_object_weak_ref (G_OBJECT (tube_conn), remote_connection_destroyed_cb, self); /* We are accepting a tube so the contact of the connection is the * initiator of the tube */ G_GNUC_BEGIN_IGNORE_DEPRECATIONS initiator_handle = tp_channel_get_initiator_handle (TP_CHANNEL (self)); connection = tp_channel_get_connection (TP_CHANNEL (self)); features = tp_simple_client_factory_dup_contact_features ( tp_proxy_get_factory (connection), connection); /* Pass ownership of tube_conn to the function */ tp_connection_get_contacts_by_handle (connection, 1, &initiator_handle, features->len, (TpContactFeature *) features->data, new_local_connection_with_contact, tube_conn, g_object_unref, G_OBJECT (self)); G_GNUC_END_IGNORE_DEPRECATIONS g_array_unref (features); }
void empathy_call_handler_start_call (EmpathyCallHandler *handler, gint64 timestamp) { EmpathyCallHandlerPriv *priv = GET_PRIV (handler); TpAccountChannelRequest *req; TpAccount *account; GHashTable *request; if (priv->call != NULL) { empathy_call_handler_start_tpfs (handler); if (tp_channel_get_requested (TP_CHANNEL (priv->call))) { /* accept outgoing channels immediately */ tp_call_channel_accept_async (priv->call, on_call_accepted_cb, NULL); } else { /* accepting incoming channels when they are INITIALISED */ if (tp_call_channel_get_state (priv->call, NULL, NULL, NULL) == TP_CALL_STATE_INITIALISED) tp_call_channel_accept_async (priv->call, on_call_accepted_cb, NULL); else priv->accept_when_initialised = TRUE; } return; } /* No TpCallChannel (we are redialing). Request a new call channel */ g_assert (priv->contact != NULL); account = empathy_contact_get_account (priv->contact); request = empathy_call_create_call_request ( empathy_contact_get_id (priv->contact), priv->initial_audio, priv->initial_video); req = tp_account_channel_request_new (account, request, timestamp); tp_account_channel_request_create_and_handle_channel_async (req, NULL, empathy_call_handler_request_cb, handler); g_object_unref (req); g_hash_table_unref (request); }
static void join_cb (GObject *source, GAsyncResult *result, gpointer user_data) { TpChannel *channel = TP_CHANNEL (source); GError *error = NULL; if (!tp_channel_join_finish (channel, result, &error)) { DEBUG ("Failed to join chat (%s): %s", tp_channel_get_identifier (channel), error->message); g_error_free (error); } }
/** * empathy_ft_handler_cancel_transfer: * @handler: an #EmpathyFTHandler * * Cancels an ongoing handler operation. Note that this doesn't destroy * the object, which will keep all the properties, altough it won't be able * to do any more I/O. */ void empathy_ft_handler_cancel_transfer (EmpathyFTHandler *handler) { EmpathyFTHandlerPriv *priv; g_return_if_fail (EMPATHY_IS_FT_HANDLER (handler)); priv = handler->priv; /* if we don't have a channel, we are hashing, so * we can just cancel the GCancellable to stop it. */ if (priv->channel == NULL) g_cancellable_cancel (priv->cancellable); else tp_channel_close_async (TP_CHANNEL (priv->channel), NULL, NULL); }
static void on_channel_close_returned (GObject *source, GAsyncResult *result, gpointer user_data) { TpChannel *channel = TP_CHANNEL (user_data); GError *error = NULL; tp_channel_close_finish (channel, result, &error); if (error != NULL) { DEBUG ("Channel.Close() failed: %s", error->message); g_clear_error (&error); } g_object_unref (channel); }
static void do_dispose (GObject *object) { EmpathyFTHandler *self = EMPATHY_FT_HANDLER (object); EmpathyFTHandlerPriv *priv = self->priv; if (priv->dispose_run) return; priv->dispose_run = TRUE; if (priv->account != NULL) { g_object_unref (priv->account); priv->account = NULL; } if (priv->contact != NULL) { g_object_unref (priv->contact); priv->contact = NULL; } if (priv->gfile != NULL) { g_object_unref (priv->gfile); priv->gfile = NULL; } if (priv->channel != NULL) { tp_channel_close_async (TP_CHANNEL (priv->channel), NULL, NULL); g_object_unref (priv->channel); priv->channel = NULL; } if (priv->cancellable != NULL) { g_object_unref (priv->cancellable); priv->cancellable = NULL; } if (priv->request != NULL) { g_hash_table_unref (priv->request); priv->request = NULL; } G_OBJECT_CLASS (empathy_ft_handler_parent_class)->dispose (object); }
static void connection_identified (TpStreamTubeChannel *self, GSocketConnection *conn, TpHandle handle, guint connection_id) { TpStreamTubeConnection *tube_conn; tube_conn = _tp_stream_tube_connection_new (conn, self); g_hash_table_insert (self->priv->tube_connections, GUINT_TO_POINTER (connection_id), tube_conn); g_object_weak_ref (G_OBJECT (tube_conn), remote_connection_destroyed_cb, self); if (can_identify_contact (self)) { TpConnection *connection; GArray *features; connection = tp_channel_get_connection (TP_CHANNEL (self)); features = tp_simple_client_factory_dup_contact_features ( tp_proxy_get_factory (connection), connection); /* Spec does not give the id with the handle */ G_GNUC_BEGIN_IGNORE_DEPRECATIONS /* Pass the ref on tube_conn to the function */ tp_connection_get_contacts_by_handle (connection, 1, &handle, features->len, (TpContactFeature *) features->data, _new_remote_connection_with_contact, tube_conn, g_object_unref, G_OBJECT (self)); G_GNUC_END_IGNORE_DEPRECATIONS g_array_unref (features); } else { g_signal_emit (self, _signals[INCOMING], 0, tube_conn); g_object_unref (tube_conn); } }
static TpChannel * create_channel (TpSimpleClientFactory *self, TpConnection *conn, const gchar *object_path, const GHashTable *properties, GError **error) { const gchar *channel_type; channel_type = tp_asv_get_string (properties, TP_PROP_CHANNEL_CHANNEL_TYPE); if (g_strcmp0 (channel_type, TP_IFACE_CHANNEL_TYPE_TEXT) == 0) { return TP_CHANNEL (tmc_text_channel_new (self, conn, object_path, properties, error)); } else { g_debug ("Unknown channel type: %s", channel_type); return TP_SIMPLE_CLIENT_FACTORY_CLASS (tmc_client_factory_parent_class)->create_channel (self, conn, object_path, properties, error); } }
static gboolean can_identify_contact (TpStreamTubeChannel *self) { TpHandleType handle_type; tp_channel_get_handle (TP_CHANNEL (self), &handle_type); /* With contact stream tube, it's always the same contact connecting to the * tube */ if (handle_type == TP_HANDLE_TYPE_CONTACT) return TRUE; /* Room stream tube, we need either the Credentials or Port access control * to properly identify connections. */ if (self->priv->access_control == TP_SOCKET_ACCESS_CONTROL_CREDENTIALS || self->priv->access_control == TP_SOCKET_ACCESS_CONTROL_PORT) return TRUE; return FALSE; }
static gboolean has_ongoing_calls (EmpathyCallObserver *self) { GList *l; for (l = self->priv->channels; l != NULL; l = l->next) { TpChannel *channel = TP_CHANNEL (l->data); GQuark type = tp_channel_get_channel_type_id (channel); /* Check that Call channels are not ended */ if (type == TP_IFACE_QUARK_CHANNEL_TYPE_CALL && tp_call_channel_get_state (TP_CALL_CHANNEL (channel), NULL, NULL, NULL) == TP_CALL_STATE_ENDED) continue; return TRUE; } return FALSE; }
static void on_channel_ready (GObject *source_object, GAsyncResult *result, gpointer user_data) { TpChannel *tp_chan = TP_CHANNEL (source_object); McdChannel *channel, **channel_ptr = user_data; McdChannelPrivate *priv; gboolean requested, valid; GError *error = NULL; if (!tp_proxy_prepare_finish (tp_chan, result, &error)) { DEBUG ("failed to prepare channel: %s", error->message); g_clear_error (&error); return; } channel = *channel_ptr; if (channel) g_object_remove_weak_pointer ((GObject *)channel, (gpointer)channel_ptr); g_slice_free (McdChannel *, channel_ptr); if (error) { DEBUG ("got error: %s", error->message); return; } if (!channel) return; DEBUG ("channel %p is ready", channel); priv = channel->priv; requested = tp_asv_get_boolean (tp_channel_borrow_immutable_properties (tp_chan), TP_IFACE_CHANNEL ".Requested", &valid); if (valid) priv->outgoing = requested; }
static void mex_telepathy_channel_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { MexTelepathyChannel *self = MEX_TELEPATHY_CHANNEL (object); MexTelepathyChannelPrivate *priv = self->priv; switch (property_id) { case PROP_CHANNEL: priv->channel = TP_CHANNEL (g_value_get_object (value)); mex_telepathy_channel_initialize_channel(self); break; case PROP_CONNECTION: priv->connection = TP_CONNECTION (g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } }
static void mex_telepathy_channel_on_content_added (TfChannel *channel, TfContent *content, gpointer user_data) { MexTelepathyChannel *self = MEX_TELEPATHY_CHANNEL (user_data); MexTelepathyChannelPrivate *priv = self->priv; GstPad *srcpad, *sinkpad; FsMediaType mtype; GstElement *element; GstStateChangeReturn ret; MEX_DEBUG ("Content added"); g_object_get (content, "sink-pad", &sinkpad, "media-type", &mtype, NULL); switch (mtype) { case FS_MEDIA_TYPE_AUDIO: MEX_DEBUG ("Audio content added"); element = gst_parse_bin_from_description ( "autoaudiosrc ! audioresample ! audioconvert ! volume name=micvolume", TRUE, NULL); priv->outgoing_mic = element; priv->mic_volume = gst_bin_get_by_name (GST_BIN (priv->outgoing_mic), "micvolume"); break; case FS_MEDIA_TYPE_VIDEO: MEX_DEBUG ("Video content added"); element = mex_telepathy_channel_setup_video_source (self, content); break; default: MEX_WARNING ("Unknown media type"); g_object_unref (sinkpad); return; } g_signal_connect (content, "src-pad-added", G_CALLBACK (mex_telepathy_channel_on_src_pad_added), self); gst_bin_add (GST_BIN (priv->pipeline), element); srcpad = gst_element_get_pad (element, "src"); if (GST_PAD_LINK_FAILED (gst_pad_link (srcpad, sinkpad))) { tp_channel_close_async (TP_CHANNEL (priv->channel), NULL, NULL); MEX_WARNING ("Couldn't link source pipeline !?"); return; } ret = gst_element_set_state (element, GST_STATE_PLAYING); if (ret == GST_STATE_CHANGE_FAILURE) { tp_channel_close_async (TP_CHANNEL (priv->channel), NULL, NULL); MEX_WARNING ("source pipeline failed to start!?"); return; } g_object_unref (srcpad); g_object_unref (sinkpad); }
static void mex_telepathy_channel_on_src_pad_added (TfContent *content, TpHandle handle, FsStream *stream, GstPad *pad, FsCodec *codec, gpointer user_data) { MexTelepathyChannel *self = MEX_TELEPATHY_CHANNEL (user_data); MexTelepathyChannelPrivate *priv = self->priv; gchar *cstr = fs_codec_to_string (codec); FsMediaType mtype; GstPad *sinkpad; GstElement *element; GstStateChangeReturn ret; /* Upon pad added, clear the "in progress" box+padding */ clutter_actor_hide (CLUTTER_ACTOR (priv->busy_box)); clutter_actor_show (CLUTTER_ACTOR (priv->full_frame) ); MEX_DEBUG ("New src pad: %s", cstr); g_object_get (content, "media-type", &mtype, NULL); switch (mtype) { case FS_MEDIA_TYPE_AUDIO: element = gst_parse_bin_from_description ( "audioconvert ! audioresample ! audioconvert ! autoaudiosink", TRUE, NULL); break; case FS_MEDIA_TYPE_VIDEO: element = priv->incoming_sink; break; default: MEX_WARNING ("Unknown media type"); return; } if (!gst_bin_add (GST_BIN (priv->pipeline), element)) { MEX_WARNING ("Failed to add sink element to pipeline"); } sinkpad = gst_element_get_pad (element, "sink"); ret = gst_element_set_state (element, GST_STATE_PLAYING); if (ret == GST_STATE_CHANGE_FAILURE) { tp_channel_close_async (TP_CHANNEL (priv->channel), NULL, NULL); MEX_WARNING ("Failed to start tee sink pipeline !?"); return; } if (GST_PAD_LINK_FAILED (gst_pad_link (pad, sinkpad))) { tp_channel_close_async (TP_CHANNEL (priv->channel), NULL, NULL); MEX_WARNING ("Couldn't link sink pipeline !?"); return; } g_object_unref (sinkpad); /* Start in FULL mode */ mex_telepathy_channel_set_tool_mode (self, TOOL_MODE_FULL, 100); }
static void mex_telepathy_channel_initialize_channel (MexTelepathyChannel *self) { MexTelepathyChannelPrivate *priv = self->priv; GstBus *bus; GstElement *pipeline; GstStateChangeReturn ret; gboolean ready; TpHandle contactHandle = tp_channel_get_handle (priv->channel, NULL); TpContactFeature features[] = { TP_CONTACT_FEATURE_ALIAS, TP_CONTACT_FEATURE_AVATAR_DATA, TP_CONTACT_FEATURE_AVATAR_TOKEN}; MEX_INFO ("New channel"); if (contactHandle) tp_connection_get_contacts_by_handle ( priv->connection, 1, &contactHandle, 1, features, mex_telepathy_channel_on_contact_fetched, self, NULL, NULL); pipeline = gst_pipeline_new (NULL); ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); if (ret == GST_STATE_CHANGE_FAILURE) { tp_channel_close_async (TP_CHANNEL (priv->channel), NULL, NULL); g_object_unref (pipeline); MEX_WARNING ("Failed to start an empty pipeline !?"); return; } priv->pipeline = pipeline; bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); priv->buswatch = gst_bus_add_watch (bus, mex_telepathy_channel_on_bus_watch, self); g_object_unref (bus); tf_channel_new_async (priv->channel, mex_telepathy_channel_new_tf_channel, self); tpy_cli_channel_type_call_call_accept (TP_PROXY (priv->channel), -1, NULL, NULL, NULL, NULL); priv->channel = g_object_ref (priv->channel); g_signal_connect (priv->channel, "notify::ready", G_CALLBACK (mex_telepathy_channel_on_ready), self); g_signal_connect (priv->channel, "invalidated", G_CALLBACK (mex_telepathy_channel_on_proxy_invalidated), self); g_signal_connect (TPY_CALL_CHANNEL (priv->channel), "state-changed", G_CALLBACK (mex_telepathy_channel_on_call_state_changed), self); g_object_get (priv->channel, "ready", &ready, NULL); if (ready) mex_telepathy_channel_on_ready (TPY_CALL_CHANNEL (priv->channel), NULL, self); }
static void process_tp_chat (EmpathyChatManager *self, EmpathyTpChat *tp_chat, TpAccount *account, gint64 user_action_time) { EmpathyChatManagerPriv *priv = GET_PRIV (self); EmpathyChat *chat = NULL; const gchar *id; EmpathyChatWindow *window; id = empathy_tp_chat_get_id (tp_chat); if (!tp_str_empty (id)) { chat = empathy_chat_window_find_chat (account, id, tp_text_channel_is_sms_channel ((TpTextChannel *) tp_chat)); } if (chat != NULL) { empathy_chat_set_tp_chat (chat, tp_chat); } else { GHashTable *chats = NULL; chat = empathy_chat_new (tp_chat); /* empathy_chat_new returns a floating reference as EmpathyChat is * a GtkWidget. This reference will be taken by a container * (a GtkNotebook) when we'll call empathy_chat_window_present_chat */ priv->num_displayed_chat++; DEBUG ("Chat displayed; we are now displaying %u chat", priv->num_displayed_chat); g_signal_emit (self, signals[DISPLAYED_CHATS_CHANGED], 0, priv->num_displayed_chat); /* Set the saved message in the channel if we have one. */ chats = g_hash_table_lookup (priv->messages, tp_proxy_get_object_path (account)); if (chats != NULL) { const gchar *msg = g_hash_table_lookup (chats, id); if (msg != NULL) empathy_chat_set_text (chat, msg); } g_object_weak_ref ((GObject *) chat, chat_destroyed_cb, self); } window = empathy_chat_window_present_chat (chat, user_action_time); if (priv->individual_mgr == NULL) { /* We want to cache it as soon it's created */ tp_g_signal_connect_object (window, "notify::individual-manager", G_CALLBACK (individual_mgr_cb), self, 0); } if (empathy_tp_chat_is_invited (tp_chat, NULL)) { /* We have been invited to the room. Add ourself as member as this * channel has been approved. */ tp_channel_join_async (TP_CHANNEL (tp_chat), "", join_cb, self); } }
static void channel_ready (GObject *source, GAsyncResult *result, gpointer user_data) { ChVisitor *visitor = (ChVisitor*) user_data; TpChannel *channel; const gchar *ident; TpMessage *message; GError *error = NULL; if (!tp_proxy_prepare_finish (source, result, &error)) { g_printerr ("error loading channel: %s\n", error->message); return; } channel = TP_CHANNEL (source); ident = tp_channel_get_identifier (channel); if (verbose > 0) { g_printerr ("channel ready \"%s\" (type %s)\n", ident, tp_channel_get_channel_type (channel)); } GList *messages, *iter; if (TP_IS_TEXT_CHANNEL (channel)) { messages = tp_text_channel_dup_pending_messages ( TP_TEXT_CHANNEL (channel)); for (iter = messages; iter; iter = iter->next) { TpMessage *message = TP_MESSAGE (iter->data); message_cb (message); } if (acknowledge) { tp_text_channel_ack_messages_async (TP_TEXT_CHANNEL (channel), messages, ack_messages_cb, NULL); } g_list_free_full (messages, g_object_unref); if (send_message && !has_sent_message_to (ident)) { message = tp_client_message_new_text(0, msg_buffer); g_ptr_array_add (messages_sent, g_strdup (ident)); ch_visitor_incref (visitor); tp_text_channel_send_message_async (TP_TEXT_CHANNEL (channel), message, 0, send_message_cb, visitor); } } else { g_printerr ("error loading channel: %s is not a text channel\n", tp_channel_get_identifier (channel)); } ch_visitor_decref (visitor); }
static void tp_stream_tube_channel_constructed (GObject *obj) { TpStreamTubeChannel *self = (TpStreamTubeChannel *) obj; void (*chain_up) (GObject *) = ((GObjectClass *) tp_stream_tube_channel_parent_class)->constructed; TpChannel *chan = (TpChannel *) obj; GHashTable *props; GError *err = NULL; if (chain_up != NULL) chain_up (obj); if (tp_channel_get_channel_type_id (chan) != TP_IFACE_QUARK_CHANNEL_TYPE_STREAM_TUBE) { GError error = { TP_DBUS_ERRORS, TP_DBUS_ERROR_INCONSISTENT, "Channel is not a stream tube" }; DEBUG ("Channel is not a stream tube: %s", tp_channel_get_channel_type ( chan)); tp_proxy_invalidate (TP_PROXY (self), &error); return; } props = _tp_channel_get_immutable_properties (TP_CHANNEL (self)); if (tp_asv_get_string (props, TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SERVICE) == NULL) { GError error = { TP_DBUS_ERRORS, TP_DBUS_ERROR_INCONSISTENT, "Tube doesn't have StreamTube.Service property" }; DEBUG ("%s", error.message); tp_proxy_invalidate (TP_PROXY (self), &error); return; } /* Tube.Parameters is immutable for incoming tubes. For outgoing ones, * it's defined when offering the tube. */ if (!tp_channel_get_requested (TP_CHANNEL (self))) { GHashTable *params; params = tp_asv_get_boxed (props, TP_PROP_CHANNEL_INTERFACE_TUBE_PARAMETERS, TP_HASH_TYPE_STRING_VARIANT_MAP); if (params == NULL) { DEBUG ("Incoming tube doesn't have Tube.Parameters property"); self->priv->parameters = tp_asv_new (NULL, NULL); } else { self->priv->parameters = g_boxed_copy ( TP_HASH_TYPE_STRING_VARIANT_MAP, params); } } tp_cli_channel_type_stream_tube_connect_to_connection_closed ( TP_CHANNEL (self), connection_closed_cb, NULL, NULL, G_OBJECT (self), &err); if (err != NULL) { DEBUG ("Failed to connect to ConnectionClosed signal: %s", err->message); g_error_free (err); } }
static void _channel_accepted (TpChannel *channel, const GValue *addressv, const GError *in_error, gpointer user_data, GObject *obj) { TpStreamTubeChannel *self = (TpStreamTubeChannel *) obj; GSocketAddress *remote_address; GError *error = NULL; if (in_error != NULL) { DEBUG ("Failed to Accept Stream Tube: %s", in_error->message); operation_failed (self, in_error); return; } tp_cli_channel_type_stream_tube_connect_to_new_local_connection ( TP_CHANNEL (self), new_local_connection_cb, NULL, NULL, G_OBJECT (self), &error); if (error != NULL) { DEBUG ("Failed to connect to NewLocalConnection signal"); operation_failed (self, error); g_error_free (error); return; } remote_address = tp_g_socket_address_from_variant (self->priv->socket_type, addressv, &error); if (error != NULL) { DEBUG ("Failed to convert address: %s", error->message); operation_failed (self, error); g_error_free (error); return; } /* Connect to CM */ g_socket_set_blocking (self->priv->client_socket, FALSE); g_socket_connect (self->priv->client_socket, remote_address, NULL, &error); if (error == NULL) { /* Socket is connected */ client_socket_connected (self); goto out; } else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PENDING)) { /* We have to wait that the socket is connected */ GSource *source; source = g_socket_create_source (self->priv->client_socket, G_IO_OUT, NULL); g_source_attach (source, g_main_context_get_thread_default ()); g_source_set_callback (source, (GSourceFunc) client_socket_cb, self, NULL); g_error_free (error); g_source_unref (source); } else { DEBUG ("Failed to connect to CM: %s", error->message); operation_failed (self, error); g_error_free (error); } out: g_object_unref (remote_address); }
/** * tp_stream_tube_channel_offer_async: * @self: an outgoing #TpStreamTubeChannel * @params: (allow-none) (transfer none): parameters of the tube, or %NULL * @callback: a callback to call when the tube has been offered * @user_data: data to pass to @callback * * Offer an outgoing stream tube. When the tube has been offered, @callback * will be called. You can then call tp_stream_tube_channel_offer_finish() * to get the result of the operation. * * You have to connect to the #TpStreamTubeChannel::incoming signal to get a * #TpStreamTubeConnection each time a contact establishes a connection to * the tube. * * Since: 0.13.2 */ void tp_stream_tube_channel_offer_async (TpStreamTubeChannel *self, GHashTable *params, GAsyncReadyCallback callback, gpointer user_data) { GHashTable *properties; GHashTable *supported_sockets; GError *error = NULL; g_return_if_fail (TP_IS_STREAM_TUBE_CHANNEL (self)); g_return_if_fail (self->priv->result == NULL); g_return_if_fail (tp_channel_get_requested (TP_CHANNEL (self))); if (self->priv->service != NULL) { g_critical ("Can't reoffer Tube!"); return; } self->priv->result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, tp_stream_tube_channel_offer_async); properties = _tp_channel_get_immutable_properties (TP_CHANNEL (self)); supported_sockets = tp_asv_get_boxed (properties, TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SUPPORTED_SOCKET_TYPES, TP_HASH_TYPE_SUPPORTED_SOCKET_MAP); if (!_tp_set_socket_address_type_and_access_control_type (supported_sockets, &self->priv->socket_type, &self->priv->access_control, &error)) { operation_failed (self, error); g_clear_error (&error); return; } DEBUG ("Using socket type %u with access control %u", self->priv->socket_type, self->priv->access_control); self->priv->service = g_socket_service_new (); switch (self->priv->socket_type) { #ifdef HAVE_GIO_UNIX case TP_SOCKET_ADDRESS_TYPE_UNIX: { self->priv->address = _tp_create_temp_unix_socket ( self->priv->service, &error); /* check there wasn't an error on the final attempt */ if (self->priv->address == NULL) { operation_failed (self, error); g_clear_error (&error); return; } } break; #endif /* HAVE_GIO_UNIX */ case TP_SOCKET_ADDRESS_TYPE_IPV4: case TP_SOCKET_ADDRESS_TYPE_IPV6: { GInetAddress *localhost; GSocketAddress *in_address; localhost = g_inet_address_new_loopback ( self->priv->socket_type == TP_SOCKET_ADDRESS_TYPE_IPV4 ? G_SOCKET_FAMILY_IPV4 : G_SOCKET_FAMILY_IPV6); in_address = g_inet_socket_address_new (localhost, 0); g_socket_listener_add_address ( G_SOCKET_LISTENER (self->priv->service), in_address, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, NULL, &self->priv->address, &error); g_object_unref (localhost); g_object_unref (in_address); if (error != NULL) { operation_failed (self, error); g_clear_error (&error); return; } break; } default: /* should have already errored */ g_assert_not_reached (); break; } tp_g_signal_connect_object (self->priv->service, "incoming", G_CALLBACK (service_incoming_cb), self, 0); g_socket_service_start (self->priv->service); _offer_with_address (self, params); }
/** * tp_stream_tube_channel_accept_async: * @self: an incoming #TpStreamTubeChannel * @callback: a callback to call when the tube has been accepted * @user_data: data to pass to @callback * * Accept an incoming stream tube. When the tube has been accepted, @callback * will be called. You can then call tp_stream_tube_channel_accept_finish() * to get a #TpStreamTubeConnection connected to the tube. * * Since: 0.13.2 */ void tp_stream_tube_channel_accept_async (TpStreamTubeChannel *self, GAsyncReadyCallback callback, gpointer user_data) { GHashTable *properties; GHashTable *supported_sockets; GError *error = NULL; g_return_if_fail (TP_IS_STREAM_TUBE_CHANNEL (self)); g_return_if_fail (self->priv->result == NULL); if (self->priv->access_control_param != NULL) { g_simple_async_report_error_in_idle (G_OBJECT (self), callback, user_data, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Tube has already be accepted"); return; } self->priv->result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, tp_stream_tube_channel_accept_async); properties = _tp_channel_get_immutable_properties (TP_CHANNEL (self)); supported_sockets = tp_asv_get_boxed (properties, TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SUPPORTED_SOCKET_TYPES, TP_HASH_TYPE_SUPPORTED_SOCKET_MAP); if (!_tp_set_socket_address_type_and_access_control_type (supported_sockets, &self->priv->socket_type, &self->priv->access_control, &error)) { operation_failed (self, error); g_clear_error (&error); return; } DEBUG ("Using socket type %u with access control %u", self->priv->socket_type, self->priv->access_control); self->priv->client_socket = _tp_create_client_socket (self->priv->socket_type, &error); if (error != NULL) { DEBUG ("Failed to create socket: %s", error->message); operation_failed (self, error); g_clear_error (&error); return; } switch (self->priv->access_control) { case TP_SOCKET_ACCESS_CONTROL_LOCALHOST: /* Put a dummy value */ self->priv->access_control_param = tp_g_value_slice_new_uint (0); break; case TP_SOCKET_ACCESS_CONTROL_PORT: { GSocketAddress *addr; guint16 port; addr = g_socket_get_local_address (self->priv->client_socket, &error); if (addr == NULL) { DEBUG ("Failed to get local address of client socket: %s", error->message); operation_failed (self, error); g_error_free (error); return; } port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr)); self->priv->access_control_param = tp_g_value_slice_new_uint (port); g_object_unref (addr); } break; case TP_SOCKET_ACCESS_CONTROL_CREDENTIALS: self->priv->access_control_param = tp_g_value_slice_new_byte ( g_random_int_range (0, G_MAXUINT8)); break; default: g_assert_not_reached (); } /* Call Accept */ tp_cli_channel_type_stream_tube_call_accept (TP_CHANNEL (self), -1, self->priv->socket_type, self->priv->access_control, self->priv->access_control_param, _channel_accepted, NULL, NULL, G_OBJECT (self)); }