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);
}
Пример #2
0
static void
create_channel_cb (GObject *acr,
    GAsyncResult *res,
    gpointer user_data)
{
  GSimpleAsyncResult *simple = user_data;
  CreateTubeData *data;
  GSocketListener *listener = NULL;
  gchar *dir;
  GSocket *socket = NULL;
  GSocketAddress *socket_address = NULL;
  GValue *address;
  GHashTable *parameters;
  GError *error = NULL;

  data = g_simple_async_result_get_op_res_gpointer (simple);

  if (g_cancellable_is_cancelled (data->op_cancellable))
    {
      g_object_unref (simple);
      return;
    }

  data->channel = tp_account_channel_request_create_and_handle_channel_finish (
      TP_ACCOUNT_CHANNEL_REQUEST (acr), res, NULL, &error);
   if (data->channel == NULL)
    goto OUT;

  data->invalidated_id = g_signal_connect (data->channel, "invalidated",
      G_CALLBACK (create_tube_channel_invalidated_cb), simple);

  /* We are client side, but we have to offer a socket... So we offer an unix
   * socket on which the service side can connect. We also create an IPv4 socket
   * on which the ssh client can connect. When both sockets are connected,
   * we can forward all communications between them. */

  listener = g_socket_listener_new ();

  /* Create temporary file for our unix socket */
  dir = g_build_filename (g_get_tmp_dir (), "telepathy-ssh-XXXXXX", NULL);
  dir = mkdtemp (dir);
  data->unix_path = g_build_filename (dir, "unix-socket", NULL);
  g_free (dir);

  /* Create the unix socket, and listen for connection on it */
  socket = g_socket_new (G_SOCKET_FAMILY_UNIX, G_SOCKET_TYPE_STREAM,
      G_SOCKET_PROTOCOL_DEFAULT, &error);
  if (socket == NULL)
    goto OUT;
  socket_address = g_unix_socket_address_new (data->unix_path);
  if (!g_socket_bind (socket, socket_address, FALSE, &error))
    goto OUT; 
  if (!g_socket_listen (socket, &error))
    goto OUT;
  if (!g_socket_listener_add_socket (listener, socket, NULL, &error))
    goto OUT;

  g_socket_listener_accept_async (listener, data->op_cancellable,
    create_tube_socket_connected_cb, g_object_ref (simple));

  /* Offer the socket */
  address = tp_address_variant_from_g_socket_address (socket_address,
      TP_SOCKET_ADDRESS_TYPE_UNIX, &error);
  if (address == NULL)
    goto OUT;
  parameters = g_hash_table_new (NULL, NULL);
  data->offer_call = tp_cli_channel_type_stream_tube_call_offer (data->channel,
      -1,
      TP_SOCKET_ADDRESS_TYPE_UNIX, address,
      TP_SOCKET_ACCESS_CONTROL_LOCALHOST, parameters,
      create_tube_offer_cb, g_object_ref (simple), g_object_unref, NULL);
  tp_g_value_slice_free (address);
  g_hash_table_unref (parameters);

OUT:

  if (error != NULL)
    create_tube_complete (simple, error);

  tp_clear_object (&listener);
  tp_clear_object (&socket);
  tp_clear_object (&socket_address);
  g_clear_error (&error);
  g_object_unref (simple);
}