/** * tp_stream_tube_channel_dup_parameters_vardict: * @self: a #TpStreamTubeChannel * * Return the parameters of the dbus-tube channel in a variant of * type %G_VARIANT_TYPE_VARDICT whose keys are strings representing * parameter names and values are variants representing corresponding * parameter values set by the offerer when offering this channel. * * The GVariant returned is %NULL if this is an outgoing tube that has not * yet been offered or the parameters property has not been set. * * Use g_variant_lookup(), g_variant_lookup_value(), or tp_vardict_get_uint32() * and similar functions for convenient access to the values. * * Returns: (transfer full): a new reference to a #GVariant * * Since: 0.19.10 */ GVariant * tp_stream_tube_channel_dup_parameters_vardict (TpStreamTubeChannel *self) { g_return_val_if_fail (TP_IS_STREAM_TUBE_CHANNEL (self), NULL); if (self->priv->parameters == NULL) return NULL; return _tp_asv_to_vardict (self->priv->parameters); }
static void create_channel_cb (GObject *acr, GAsyncResult *res, gpointer user_data) { GSimpleAsyncResult *simple = user_data; CreateTubeData *data; GError *error = NULL; data = g_simple_async_result_get_op_res_gpointer (simple); data->channel = tp_account_channel_request_create_and_handle_channel_finish ( TP_ACCOUNT_CHANNEL_REQUEST (acr), res, NULL, &error); if (!TP_IS_STREAM_TUBE_CHANNEL (data->channel)) { tp_clear_object (&data->channel); if (error == NULL) error = g_error_new_literal (TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED, "Not supported channel type"); create_tube_complete (simple, error); g_clear_error (&error); g_object_unref (simple); return; } g_signal_connect (data->channel, "invalidated", G_CALLBACK (create_tube_channel_invalidated_cb), simple); g_signal_connect_data (data->channel, "incoming", G_CALLBACK (create_tube_incoming_cb), g_object_ref (simple), (GClosureNotify) g_object_unref, 0); tp_stream_tube_channel_offer_async (TP_STREAM_TUBE_CHANNEL (data->channel), NULL, create_tube_offer_cb, g_object_ref (simple)); g_object_unref (simple); }
static void handle_channels_cb (TpSimpleHandler *handler, TpAccount *account, TpConnection *connection, GList *channels, GList *requests_satisfied, gint64 user_action_time, TpHandleChannelsContext *context, gpointer user_data) { VinoTubeServersManager *self = user_data; VinoTubeServer *server; GdkDisplay *display; GdkScreen *screen; /* the server is listenning only on lo as only the tube is supposed to connect to it */ gchar * network_interface = "lo"; GList *l; TpStreamTubeChannel *channel = NULL; for (l = channels; l != NULL; l = g_list_next (l)) { TpStreamTubeChannel *chan = l->data; if (!TP_IS_STREAM_TUBE_CHANNEL (chan)) continue; if (tp_proxy_get_invalidated (chan) != NULL) continue; if (tp_strdiff (tp_stream_tube_channel_get_service (chan), "rfb")) continue; channel = chan; break; } if (channel == NULL) { /* No stream tube channel ?! */ GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, "No stream tube channel" }; tp_handle_channels_context_fail (context, &error); return; } display = gdk_display_get_default (); screen = gdk_display_get_default_screen (display); server = g_object_new (VINO_TYPE_TUBE_SERVER, "display-status-icon", 0, "prompt-enabled", 0, "view-only", 0, "network-interface", network_interface, "use-alternative-port", 1, "alternative-port", self->priv->alternative_port, "auth-methods", 1, "require-encryption", 0, "vnc-password", NULL, "on-hold", 0, "screen", screen, "lock-screen", 0, "disable-background", 0, "use-upnp", 0, "tube", channel, NULL); self->priv->vino_tube_servers = g_slist_prepend (self->priv->vino_tube_servers, server); g_signal_connect (G_OBJECT (server), "disconnected", G_CALLBACK (vino_tube_servers_manager_disconnected_cb), self); self->priv->alternative_port++; vino_tube_server_share_with_tube (server, NULL); tp_handle_channels_context_accept (context); }
/** * 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)); }
/** * 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); }