~ubuntu-branches/ubuntu/maverick/telepathy-salut/maverick

« back to all changes in this revision

Viewing changes to src/salut-tubes-channel.c

  • Committer: Bazaar Package Importer
  • Author(s): Laurent Bigonville
  • Date: 2008-09-17 19:03:47 UTC
  • mfrom: (7.1.8 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080917190347-fhkvbcpf8jp8wxkw
Tags: 0.3.3-2
* Use my debian.org address in Uploaders
* debian/patches/fix-activity-announce.patch:
  - Only announce OLPC activity we actually joined (dev.laptop.org #8441)

Show diffs side-by-side

added added

removed removed

Lines of Context:
30
30
#include <telepathy-glib/channel-iface.h>
31
31
#include <telepathy-glib/interfaces.h>
32
32
#include <telepathy-glib/dbus.h>
 
33
#include <telepathy-glib/svc-channel.h>
33
34
 
34
35
#include <gibber/gibber-muc-connection.h>
 
36
#include <gibber/gibber-bytestream-muc.h>
35
37
#include <gibber/gibber-xmpp-stanza.h>
36
38
#include <gibber/gibber-namespaces.h>
 
39
#include <gibber/gibber-xmpp-error.h>
37
40
 
38
41
#define DEBUG_FLAG DEBUG_TUBES
39
42
#include "debug.h"
40
 
#include "extensions/extensions.h"
41
43
#include "salut-util.h"
42
44
#include "salut-connection.h"
43
45
#include "salut-contact.h"
44
46
#include "salut-muc-channel.h"
45
47
#include "tube-iface.h"
46
48
#include "tube-dbus.h"
 
49
#include "tube-stream.h"
47
50
 
48
51
#define SALUT_CHANNEL_TUBE_TYPE \
49
52
    (dbus_g_type_get_struct ("GValueArray", \
59
62
    (dbus_g_type_get_struct ("GValueArray", \
60
63
      G_TYPE_UINT, G_TYPE_STRING, G_TYPE_INVALID))
61
64
 
62
 
/* XXX make this conditionnale */
63
 
#define HAVE_DBUS_TUBE 1
64
 
 
65
65
static void
66
66
channel_iface_init (gpointer g_iface, gpointer iface_data);
67
67
static void
69
69
 
70
70
G_DEFINE_TYPE_WITH_CODE (SalutTubesChannel, salut_tubes_channel, G_TYPE_OBJECT,
71
71
    G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL, channel_iface_init);
72
 
    G_IMPLEMENT_INTERFACE (SALUT_TYPE_SVC_CHANNEL_TYPE_TUBES, tubes_iface_init);
 
72
    G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_TUBES, tubes_iface_init);
73
73
    G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_GROUP,
74
74
        tp_external_group_mixin_iface_init);
75
75
    G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_IFACE, NULL);
105
105
};
106
106
 
107
107
#define SALUT_TUBES_CHANNEL_GET_PRIVATE(obj) \
108
 
  ((SalutTubesChannelPrivate *) obj->priv)
 
108
  ((SalutTubesChannelPrivate *) ((SalutTubesChannel *)obj)->priv)
109
109
 
110
 
static gboolean update_tubes_info (SalutTubesChannel *self, gboolean request);
111
 
static void muc_connection_received_stanza_cb (GibberMucConnection *conn,
112
 
    const gchar *sender, GibberXmppStanza *stanza, gpointer user_data);
113
 
static void muc_connection_lost_sender_cb (GibberMucConnection *conn,
114
 
    const gchar *sender, gpointer user_data);
 
110
static gboolean update_tubes_info (SalutTubesChannel *self);
 
111
static void muc_connection_lost_senders_cb (GibberMucConnection *conn,
 
112
    GArray *senders, gpointer user_data);
 
113
static void muc_connection_new_senders_cb (GibberMucConnection *conn,
 
114
    GArray *senders, gpointer user_data);
115
115
static gboolean extract_tube_information (SalutTubesChannel *self,
116
 
    GibberXmppNode *tube_node, SalutTubeType *type, TpHandle *initiator_handle,
117
 
    const gchar **service, GHashTable **parameters, gboolean *offering,
118
 
    guint *tube_id);
119
 
static void
120
 
create_new_tube (SalutTubesChannel *self, SalutTubeType type, TpHandle initiator,
121
 
    const gchar *service, GHashTable *parameters, const gchar *stream_id,
122
 
    guint tube_id);
 
116
    GibberXmppNode *tube_node, TpTubeType *type, TpHandle *initiator_handle,
 
117
    const gchar **service, GHashTable **parameters, guint *tube_id);
 
118
static SalutTubeIface * create_new_tube (SalutTubesChannel *self,
 
119
    TpTubeType type, TpHandle initiator, const gchar *service,
 
120
    GHashTable *parameters, guint tube_id, GibberBytestreamIface *bytestream);
123
121
 
124
122
static void
125
123
salut_tubes_channel_init (SalutTubesChannel *self)
166
164
      priv->self_handle = ((TpBaseConnection *)
167
165
          (priv->conn))->self_handle;
168
166
      break;
 
167
 
169
168
    case TP_HANDLE_TYPE_ROOM:
170
169
      g_assert (self->muc != NULL);
171
170
      priv->self_handle = self->muc->group.self_handle;
175
174
          NULL);
176
175
      g_assert (priv->muc_connection != NULL);
177
176
 
178
 
      g_signal_connect (priv->muc_connection, "received-stanza",
179
 
          G_CALLBACK (muc_connection_received_stanza_cb), self);
180
 
      g_signal_connect (priv->muc_connection, "lost-sender",
181
 
          G_CALLBACK (muc_connection_lost_sender_cb), self);
 
177
      g_signal_connect (priv->muc_connection, "new-senders",
 
178
          G_CALLBACK (muc_connection_new_senders_cb), self);
 
179
      g_signal_connect (priv->muc_connection, "lost-senders",
 
180
          G_CALLBACK (muc_connection_lost_senders_cb), self);
182
181
 
183
 
      /* request tubes infos */
184
 
      update_tubes_info (self, TRUE);
185
182
      break;
186
183
    default:
187
184
      g_assert_not_reached ();
211
208
        g_value_set_string (value, priv->object_path);
212
209
        break;
213
210
      case PROP_CHANNEL_TYPE:
214
 
        g_value_set_static_string (value, SALUT_IFACE_CHANNEL_TYPE_TUBES);
 
211
        g_value_set_static_string (value, TP_IFACE_CHANNEL_TYPE_TUBES);
215
212
        break;
216
213
      case PROP_HANDLE_TYPE:
217
214
        g_value_set_uint (value, priv->handle_type);
239
236
{
240
237
  SalutTubesChannel *chan = SALUT_TUBES_CHANNEL (object);
241
238
  SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (chan);
 
239
  const gchar *value_str;
242
240
 
243
241
  switch (property_id)
244
242
    {
246
244
        g_free (priv->object_path);
247
245
        priv->object_path = g_value_dup_string (value);
248
246
        break;
 
247
      case PROP_CHANNEL_TYPE:
 
248
        /* this property is writable in the interface (in
 
249
         * telepathy-glib > 0.7.0), but not actually
 
250
         * meaningfully changeable on this channel, so we do nothing */
 
251
        value_str = g_value_get_string (value);
 
252
        g_assert (value_str == NULL || !tp_strdiff (value_str,
 
253
              TP_IFACE_CHANNEL_TYPE_TUBES));
 
254
        break;
249
255
      case PROP_HANDLE_TYPE:
250
256
        priv->handle_type = g_value_get_uint (value);
251
257
        break;
264
270
    }
265
271
}
266
272
 
267
 
#ifdef HAVE_DBUS_TUBE
268
273
static void
269
274
d_bus_names_changed_added (SalutTubesChannel *self,
270
275
                           guint tube_id,
285
290
      G_MAXUINT);
286
291
  g_ptr_array_add (added, g_value_get_boxed (&tmp));
287
292
 
288
 
  salut_svc_channel_type_tubes_emit_d_bus_names_changed (self,
 
293
  tp_svc_channel_type_tubes_emit_d_bus_names_changed (self,
289
294
      tube_id, added, removed);
290
295
 
291
296
  for (i = 0; i < added->len; i++)
299
304
                             guint tube_id,
300
305
                             TpHandle contact)
301
306
{
 
307
  SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
302
308
  GPtrArray *added = g_ptr_array_new ();
303
309
  GArray *removed = g_array_new (FALSE, FALSE, sizeof (guint));
304
310
 
 
311
  if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
 
312
    return;
 
313
 
305
314
  g_array_append_val (removed, contact);
306
315
 
307
 
  salut_svc_channel_type_tubes_emit_d_bus_names_changed (self,
 
316
  tp_svc_channel_type_tubes_emit_d_bus_names_changed (self,
308
317
      tube_id, added, removed);
309
318
 
310
319
  g_ptr_array_free (added, TRUE);
318
327
                        const gchar *dbus_name)
319
328
{
320
329
  SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
321
 
  TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
322
 
      (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
323
330
  SalutTubeDBus *tube;
324
 
  GHashTable *names;
 
331
 
 
332
  if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
 
333
    return;
325
334
 
326
335
  tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
327
336
  if (tube == NULL)
328
337
    return;
329
338
 
330
 
  g_object_get (tube,
331
 
      "dbus-names", &names,
332
 
      NULL);
333
 
 
334
 
  g_hash_table_insert (names, GUINT_TO_POINTER (handle), g_strdup (dbus_name));
335
 
  tp_handle_ref (contact_repo, handle);
336
 
 
337
 
  /* Emit the DBusNamesChanged signal */
338
 
  d_bus_names_changed_added (self, tube_id, handle, dbus_name);
339
 
 
340
 
  g_hash_table_unref (names);
 
339
  if (salut_tube_dbus_add_name (tube, handle, dbus_name))
 
340
    {
 
341
      /* Emit the DBusNamesChanged signal */
 
342
      d_bus_names_changed_added (self, tube_id, handle, dbus_name);
 
343
    }
341
344
}
342
345
 
343
346
static void
348
351
  SalutTubeDBus *tube;
349
352
  gchar *dbus_name;
350
353
 
 
354
  if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
 
355
    return;
 
356
 
351
357
  tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
352
358
  if (tube == NULL)
353
359
    return;
360
366
 
361
367
  g_free (dbus_name);
362
368
}
363
 
#endif
364
369
 
365
370
/**
366
371
 * salut_tubes_channel_get_available_tube_types
369
374
 * on org.freedesktop.Telepathy.Channel.Type.Tubes
370
375
 */
371
376
static void
372
 
salut_tubes_channel_get_available_tube_types (SalutSvcChannelTypeTubes *iface,
 
377
salut_tubes_channel_get_available_tube_types (TpSvcChannelTypeTubes *iface,
373
378
                                              DBusGMethodInvocation *context)
374
379
{
375
380
  SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
376
381
  GArray *ret;
377
 
  SalutTubeType type;
 
382
  TpTubeType type;
378
383
 
379
384
  g_assert (SALUT_IS_TUBES_CHANNEL (self));
380
385
 
381
 
  ret = g_array_sized_new (FALSE, FALSE, sizeof (SalutTubeType), 1);
382
 
  type = SALUT_TUBE_TYPE_DBUS;
383
 
  g_array_append_val (ret, type);
384
 
  /*
385
 
  type = TP_TUBE_TYPE_STREAM_UNIX;
386
 
  g_array_append_val (ret, type);
387
 
  */
 
386
  ret = g_array_sized_new (FALSE, FALSE, sizeof (TpTubeType), 1);
 
387
  type = TP_TUBE_TYPE_DBUS;
 
388
  g_array_append_val (ret, type);
 
389
  type = TP_TUBE_TYPE_STREAM;
 
390
  g_array_append_val (ret, type);
388
391
 
389
 
  salut_svc_channel_type_tubes_return_from_get_available_tube_types (context,
 
392
  tp_svc_channel_type_tubes_return_from_get_available_tube_types (context,
390
393
      ret);
391
394
 
392
395
  g_array_free (ret, TRUE);
393
396
}
394
397
 
395
 
#ifdef HAVE_DBUS_TUBE
396
398
struct _add_in_old_dbus_tubes_data
397
399
{
398
400
  GHashTable *old_dbus_tubes;
408
410
  SalutTubeIface *tube = SALUT_TUBE_IFACE (value);
409
411
  struct _add_in_old_dbus_tubes_data *data =
410
412
    (struct _add_in_old_dbus_tubes_data *) user_data;
411
 
  SalutTubeType type;
412
 
  GHashTable *names;
 
413
  TpTubeType type;
413
414
 
414
415
  g_object_get (tube, "type", &type, NULL);
415
416
 
416
 
  if (type != SALUT_TUBE_TYPE_DBUS)
 
417
  if (type != TP_TUBE_TYPE_DBUS)
417
418
    return;
418
419
 
419
 
  g_object_get (tube, "dbus-names", &names, NULL);
420
 
  g_assert (names);
421
 
 
422
 
  if (g_hash_table_lookup (names, GUINT_TO_POINTER (data->contact)))
 
420
  if (salut_tube_dbus_handle_in_names (SALUT_TUBE_DBUS (tube),
 
421
        data->contact))
423
422
    {
424
423
      /* contact was in this tube */
425
424
      g_hash_table_insert (data->old_dbus_tubes, GUINT_TO_POINTER (tube_id),
426
425
          tube);
427
426
    }
428
 
 
429
 
  g_hash_table_unref (names);
430
427
}
431
428
 
432
429
struct
445
442
  SalutTubeDBus *tube = SALUT_TUBE_DBUS (value);
446
443
  struct _emit_d_bus_names_changed_foreach_data *data =
447
444
    (struct _emit_d_bus_names_changed_foreach_data *) user_data;
448
 
  GHashTable *names;
449
445
  SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (
450
446
      data->self);
451
 
  TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
452
 
      (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
453
 
 
454
 
  /* Remove from the D-Bus names mapping */
455
 
  g_object_get (tube, "dbus-names", &names, NULL);
456
 
  g_hash_table_remove (names, GUINT_TO_POINTER (data->contact));
457
 
  g_hash_table_unref (names);
458
 
 
459
 
  /* Emit the DBusNamesChanged signal */
460
 
  d_bus_names_changed_removed (data->self, tube_id, data->contact);
461
 
 
462
 
  tp_handle_unref (contact_repo, data->contact);
 
447
 
 
448
  if (salut_tube_dbus_remove_name (tube, data->contact))
 
449
    {
 
450
      /* Emit the DBusNamesChanged signal */
 
451
      d_bus_names_changed_removed (data->self, tube_id, data->contact);
 
452
    }
 
453
 
 
454
  /* Remove the contact as sender in the muc bytestream */
 
455
  if (priv->handle_type == TP_HANDLE_TYPE_ROOM)
 
456
    {
 
457
      GibberBytestreamIface *bytestream;
 
458
 
 
459
      g_object_get (tube, "bytestream", &bytestream, NULL);
 
460
      g_assert (bytestream != NULL);
 
461
 
 
462
      if (GIBBER_IS_BYTESTREAM_MUC (bytestream))
 
463
        {
 
464
          TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
 
465
              (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
 
466
          const gchar *sender;
 
467
 
 
468
          sender = tp_handle_inspect (contact_repo, data->contact);
 
469
          if (sender != NULL)
 
470
            gibber_bytestream_muc_remove_sender (
 
471
                GIBBER_BYTESTREAM_MUC (bytestream), sender);
 
472
        }
 
473
 
 
474
      g_object_unref (bytestream);
 
475
    }
463
476
}
464
 
#endif
465
477
 
466
 
static void
467
 
muc_connection_received_stanza_cb (GibberMucConnection *conn,
468
 
                                   const gchar *sender,
469
 
                                   GibberXmppStanza *stanza,
470
 
                                   gpointer user_data)
 
478
void
 
479
tubes_message_received (SalutTubesChannel *self,
 
480
                        const gchar *sender,
 
481
                        GibberXmppStanza *stanza)
471
482
{
472
 
  SalutTubesChannel *self = SALUT_TUBES_CHANNEL (user_data);
473
483
  SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
474
484
  TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
475
485
      (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
476
486
  TpHandle contact;
477
487
  GibberXmppNode *tubes_node;
478
488
  GSList *l;
479
 
  gboolean request = FALSE;
480
 
#ifdef HAVE_DBUS_TUBE
481
489
  GHashTable *old_dbus_tubes;
482
490
  struct _add_in_old_dbus_tubes_data add_data;
483
491
  struct _emit_d_bus_names_changed_foreach_data emit_data;
484
 
#endif
 
492
  GibberStanzaType type;
 
493
  GibberStanzaSubType sub_type;
485
494
 
486
495
  contact = tp_handle_lookup (contact_repo, sender, NULL, NULL);
487
 
  if (contact == 0)
488
 
    {
489
 
      DEBUG ("unknown sender: %s", sender);
490
 
      return;
491
 
    }
 
496
  g_assert (contact != 0);
492
497
 
493
498
  if (contact == priv->self_handle)
494
 
    /* We don't need to inspect our own presence */
 
499
    /* We don't need to inspect our own tubes */
 
500
    return;
 
501
 
 
502
  gibber_xmpp_stanza_get_type_info (stanza, &type, &sub_type);
 
503
  if (type != GIBBER_STANZA_TYPE_MESSAGE
 
504
      || sub_type != GIBBER_STANZA_SUB_TYPE_GROUPCHAT)
495
505
    return;
496
506
 
497
507
  tubes_node = gibber_xmpp_node_get_child_ns (stanza->node, "tubes",
498
508
      GIBBER_TELEPATHY_NS_TUBES);
499
 
  if (tubes_node == NULL)
500
 
    return;
501
 
 
502
 
  if (!tp_strdiff (gibber_xmpp_node_get_attribute (tubes_node, "request"),
503
 
        "true"))
504
 
    request = TRUE;
505
 
 
506
 
#ifdef HAVE_DBUS_TUBE
 
509
  g_assert (tubes_node != NULL);
 
510
 
507
511
  /* Fill old_dbus_tubes with D-BUS tubes previoulsy announced by
508
512
   * the contact */
509
513
  old_dbus_tubes = g_hash_table_new (g_direct_hash, g_direct_equal);
510
514
  add_data.old_dbus_tubes = old_dbus_tubes;
511
515
  add_data.contact = contact;
512
516
  g_hash_table_foreach (priv->tubes, add_in_old_dbus_tubes, &add_data);
513
 
#endif
514
517
 
515
518
  for (l = tubes_node->children; l != NULL; l = l->next)
516
519
    {
518
521
      const gchar *stream_id;
519
522
      SalutTubeIface *tube;
520
523
      guint tube_id;
521
 
      SalutTubeType type;
 
524
      TpTubeType type;
522
525
 
523
526
      stream_id = gibber_xmpp_node_get_attribute (tube_node, "stream-id");
524
 
      if (stream_id == NULL)
525
 
        {
526
 
          DEBUG ("no stream id attribute");
527
 
          continue;
528
 
        }
529
527
 
530
528
      extract_tube_information (self, tube_node, NULL,
531
 
          NULL, NULL, NULL, NULL, &tube_id);
 
529
          NULL, NULL, NULL, &tube_id);
532
530
      tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
533
531
 
534
532
      if (tube == NULL)
535
533
        {
536
534
          /* We don't know yet this tube */
537
535
          const gchar *service;
538
 
          SalutTubeType type;
 
536
          TpTubeType type;
539
537
          TpHandle initiator_handle;
540
538
          GHashTable *parameters;
541
539
          guint tube_id;
542
540
 
543
541
          if (extract_tube_information (self, tube_node, &type,
544
 
                &initiator_handle, &service, &parameters, NULL, &tube_id))
 
542
                &initiator_handle, &service, &parameters, &tube_id))
545
543
            {
546
 
 
547
 
#ifndef HAVE_DBUS_TUBE
548
 
              if (type == SALUT_TUBE_TYPE_DBUS)
 
544
              switch (type)
549
545
                {
550
 
                  DEBUG ("Don't create the tube as D-Bus tube support"
551
 
                      "is not built");
552
 
                  continue;
 
546
                  case TP_TUBE_TYPE_DBUS:
 
547
                    {
 
548
                      if (initiator_handle == 0)
 
549
                        {
 
550
                          DEBUG ("D-Bus tube initiator missing");
 
551
                          /* skip to the next child of <tubes> */
 
552
                          continue;
 
553
                        }
 
554
                    }
 
555
                    break;
 
556
                  case TP_TUBE_TYPE_STREAM:
 
557
                    {
 
558
                      if (initiator_handle != 0)
 
559
                        /* ignore it */
 
560
                        tp_handle_unref (contact_repo, initiator_handle);
 
561
 
 
562
                      initiator_handle = contact;
 
563
                      tp_handle_ref (contact_repo, initiator_handle);
 
564
                    }
 
565
                    break;
 
566
                  default:
 
567
                    {
 
568
                      g_assert_not_reached ();
 
569
                    }
553
570
                }
554
 
#endif
555
571
 
556
 
              create_new_tube (self, type, initiator_handle,
557
 
                  service, parameters, stream_id, tube_id);
558
 
              tube = g_hash_table_lookup (priv->tubes,
559
 
                  GUINT_TO_POINTER (tube_id));
 
572
              tube = create_new_tube (self, type, initiator_handle,
 
573
                  service, parameters, tube_id, NULL);
560
574
 
561
575
              /* the tube has reffed its initiator, no need to keep a ref */
562
576
              tp_handle_unref (contact_repo, initiator_handle);
563
577
            }
564
578
        }
565
 
#ifdef HAVE_DBUS_TUBE
566
579
      else
567
580
        {
568
581
          /* The contact is in the tube.
569
582
           * Remove it from old_dbus_tubes if needed */
570
583
          g_hash_table_remove (old_dbus_tubes, GUINT_TO_POINTER (tube_id));
571
584
        }
572
 
#endif
573
585
 
574
586
      if (tube == NULL)
575
587
        continue;
576
588
 
577
589
      g_object_get (tube, "type", &type, NULL);
578
590
 
579
 
#ifdef HAVE_DBUS_TUBE
580
 
      if (type == SALUT_TUBE_TYPE_DBUS)
 
591
      if (type == TP_TUBE_TYPE_DBUS)
581
592
        {
582
593
          /* Update mapping of handle -> D-Bus name. */
583
 
 
584
 
          GHashTable *names;
585
 
          gchar *name;
586
 
 
587
 
          g_object_get (tube, "dbus-names", &names, NULL);
588
 
          g_assert (names);
589
 
          name = g_hash_table_lookup (names, GUINT_TO_POINTER (contact));
590
 
 
591
 
          if (!name)
 
594
          if (!salut_tube_dbus_handle_in_names (SALUT_TUBE_DBUS (tube),
 
595
                contact))
592
596
            {
593
597
              /* Contact just joined the tube */
594
598
              const gchar *new_name;
604
608
                }
605
609
 
606
610
              add_name_in_dbus_names (self, tube_id, contact, new_name);
 
611
 
 
612
              /* associate the contact with his stream id */
 
613
              if (priv->handle_type == TP_HANDLE_TYPE_ROOM)
 
614
                {
 
615
                  GibberBytestreamIface *bytestream;
 
616
 
 
617
                  g_object_get (tube, "bytestream", &bytestream, NULL);
 
618
                  g_assert (bytestream != NULL);
 
619
 
 
620
                  if (GIBBER_IS_BYTESTREAM_MUC (bytestream))
 
621
                    {
 
622
                      guint16 tmp = (guint16) atoi (stream_id);
 
623
 
 
624
                      gibber_bytestream_muc_add_sender (
 
625
                          GIBBER_BYTESTREAM_MUC (bytestream), sender, tmp);
 
626
                    }
 
627
 
 
628
                  g_object_unref (bytestream);
 
629
                }
607
630
            }
608
 
 
609
 
          g_hash_table_unref (names);
610
631
        }
611
 
#endif
612
632
    }
613
633
 
614
 
#ifdef HAVE_DBUS_TUBE
615
634
  /* Tubes remaining in old_dbus_tubes was left by the contact */
616
635
  emit_data.contact = contact;
617
636
  emit_data.self = self;
619
638
      &emit_data);
620
639
 
621
640
  g_hash_table_destroy (old_dbus_tubes);
622
 
#endif
623
 
 
624
 
  if (request)
625
 
    /* Contact requested tubes information */
626
 
    update_tubes_info (self, FALSE);
627
641
}
628
642
 
629
643
static void
630
 
muc_connection_lost_sender_cb (GibberMucConnection *conn,
631
 
                               const gchar *sender,
 
644
muc_connection_new_senders_cb (GibberMucConnection *conn,
 
645
                               GArray *senders,
632
646
                               gpointer user_data)
633
647
{
634
648
  SalutTubesChannel *self = SALUT_TUBES_CHANNEL (user_data);
 
649
 
 
650
  update_tubes_info (self);
 
651
}
 
652
 
 
653
static void
 
654
muc_connection_lost_senders_cb (GibberMucConnection *conn,
 
655
                                GArray *senders,
 
656
                                gpointer user_data)
 
657
{
 
658
  SalutTubesChannel *self = SALUT_TUBES_CHANNEL (user_data);
635
659
  SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
636
660
  TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
637
661
      (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
638
 
  TpHandle contact;
639
 
  GHashTable *old_dbus_tubes;
640
 
  struct _add_in_old_dbus_tubes_data add_data;
641
 
  struct _emit_d_bus_names_changed_foreach_data emit_data;
 
662
  guint i;
642
663
 
643
 
  contact = tp_handle_lookup (contact_repo, sender, NULL, NULL);
644
 
  if (contact == 0)
 
664
  for (i = 0; i < senders->len; i++)
645
665
    {
646
 
      DEBUG ("unknown sender: %s", sender);
647
 
      return;
 
666
      gchar *sender;
 
667
      TpHandle contact;
 
668
      GHashTable *old_dbus_tubes;
 
669
      struct _add_in_old_dbus_tubes_data add_data;
 
670
      struct _emit_d_bus_names_changed_foreach_data emit_data;
 
671
 
 
672
      sender = g_array_index (senders, gchar *, i);
 
673
 
 
674
      contact = tp_handle_lookup (contact_repo, sender, NULL, NULL);
 
675
      if (contact == 0)
 
676
        {
 
677
          DEBUG ("unknown sender: %s", sender);
 
678
          return;
 
679
        }
 
680
 
 
681
      old_dbus_tubes = g_hash_table_new (g_direct_hash, g_direct_equal);
 
682
      add_data.old_dbus_tubes = old_dbus_tubes;
 
683
      add_data.contact = contact;
 
684
      g_hash_table_foreach (priv->tubes, add_in_old_dbus_tubes, &add_data);
 
685
 
 
686
      /* contact left the muc so he left all its tubes */
 
687
      emit_data.contact = contact;
 
688
      emit_data.self = self;
 
689
      g_hash_table_foreach (old_dbus_tubes, emit_d_bus_names_changed_foreach,
 
690
          &emit_data);
 
691
 
 
692
      g_hash_table_destroy (old_dbus_tubes);
648
693
    }
649
 
 
650
 
  old_dbus_tubes = g_hash_table_new (g_direct_hash, g_direct_equal);
651
 
  add_data.old_dbus_tubes = old_dbus_tubes;
652
 
  add_data.contact = contact;
653
 
  g_hash_table_foreach (priv->tubes, add_in_old_dbus_tubes, &add_data);
654
 
 
655
 
  /* contact left the muc so he left all its tubes */
656
 
  emit_data.contact = contact;
657
 
  emit_data.self = self;
658
 
  g_hash_table_foreach (old_dbus_tubes, emit_d_bus_names_changed_foreach,
659
 
      &emit_data);
660
 
 
661
 
  g_hash_table_destroy (old_dbus_tubes);
662
694
}
663
695
 
664
696
static void
671
703
  TpHandle initiator;
672
704
  gchar *service;
673
705
  GHashTable *parameters;
674
 
  SalutTubeState state;
675
 
  SalutTubeType type;
 
706
  TpTubeState state;
 
707
  TpTubeType type;
676
708
  GPtrArray *array = (GPtrArray *) user_data;
677
709
  GValue entry = {0,};
678
710
 
721
753
 * on org.freedesktop.Telepathy.Channel.Type.Tubes
722
754
 */
723
755
static void
724
 
salut_tubes_channel_list_tubes (SalutSvcChannelTypeTubes *iface,
 
756
salut_tubes_channel_list_tubes (TpSvcChannelTypeTubes *iface,
725
757
                                 DBusGMethodInvocation *context)
726
758
{
727
759
  SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
734
766
  priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
735
767
 
736
768
  ret = make_tubes_ptr_array (self, priv->tubes);
737
 
  salut_svc_channel_type_tubes_return_from_list_tubes (context, ret);
 
769
  tp_svc_channel_type_tubes_return_from_list_tubes (context, ret);
738
770
 
739
771
  for (i = 0; i < ret->len; i++)
740
772
    g_boxed_free (SALUT_CHANNEL_TUBE_TYPE, ret->pdata[i]);
760
792
    }
761
793
  DEBUG ("tube %d removed", tube_id);
762
794
 
763
 
#ifdef HAVE_DBUS_TUBE
764
795
  /* Emit the DBusNamesChanged signal */
765
796
  d_bus_names_changed_removed (self, tube_id, priv->self_handle);
766
 
#endif
767
 
 
768
 
  update_tubes_info (self, FALSE);
769
 
 
770
 
  salut_svc_channel_type_tubes_emit_tube_closed (self, tube_id);
 
797
 
 
798
  update_tubes_info (self);
 
799
 
 
800
  tp_svc_channel_type_tubes_emit_tube_closed (self, tube_id);
771
801
}
772
802
 
773
803
static void
779
809
 
780
810
  g_object_get (tube, "id", &tube_id, NULL);
781
811
 
782
 
  salut_svc_channel_type_tubes_emit_tube_state_changed (self, tube_id,
783
 
      SALUT_TUBE_STATE_OPEN);
 
812
  tp_svc_channel_type_tubes_emit_tube_state_changed (self, tube_id,
 
813
      TP_TUBE_STATE_OPEN);
784
814
}
785
815
 
786
 
static void
 
816
static SalutTubeIface *
787
817
create_new_tube (SalutTubesChannel *self,
788
 
                 SalutTubeType type,
 
818
                 TpTubeType type,
789
819
                 TpHandle initiator,
790
820
                 const gchar *service,
791
821
                 GHashTable *parameters,
792
 
                 const gchar *stream_id,
793
 
                 guint tube_id)
 
822
                 guint tube_id,
 
823
                 GibberBytestreamIface *bytestream)
794
824
{
795
825
  SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
796
826
  SalutTubeIface *tube;
797
 
  SalutTubeState state;
 
827
  TpTubeState state;
798
828
  GibberMucConnection *muc_connection = NULL;
799
829
 
800
830
  if (self->muc != NULL)
802
832
 
803
833
  switch (type)
804
834
    {
805
 
#ifdef HAVE_DBUS_TUBE
806
 
    case SALUT_TUBE_TYPE_DBUS:
 
835
    case TP_TUBE_TYPE_DBUS:
807
836
      tube = SALUT_TUBE_IFACE (salut_tube_dbus_new (priv->conn,
808
837
          priv->handle, priv->handle_type, priv->self_handle, muc_connection,
809
 
          initiator, service, parameters, stream_id, tube_id));
 
838
          initiator, service, parameters, tube_id, bytestream));
810
839
      break;
811
 
#endif
812
 
      /*
813
 
    case TP_TUBE_TYPE_STREAM_UNIX:
 
840
    case TP_TUBE_TYPE_STREAM:
814
841
      tube = SALUT_TUBE_IFACE (salut_tube_stream_new (priv->conn,
815
842
          priv->handle, priv->handle_type, priv->self_handle, initiator,
816
843
          service, parameters, tube_id));
817
844
      break;
818
 
      */
819
845
    default:
820
846
      g_assert_not_reached ();
821
847
    }
822
848
 
823
849
  DEBUG ("create tube %u", tube_id);
824
850
  g_hash_table_insert (priv->tubes, GUINT_TO_POINTER (tube_id), tube);
825
 
  update_tubes_info (self, FALSE);
 
851
  update_tubes_info (self);
826
852
 
827
853
  g_object_get (tube, "state", &state, NULL);
828
854
 
829
 
  salut_svc_channel_type_tubes_emit_new_tube (self,
 
855
  tp_svc_channel_type_tubes_emit_new_tube (self,
830
856
      tube_id,
831
857
      initiator,
832
858
      type,
834
860
      parameters,
835
861
      state);
836
862
 
837
 
#ifdef HAVE_DBUS_TUBE
838
 
  if (type == SALUT_TUBE_TYPE_DBUS &&
839
 
      state != SALUT_TUBE_STATE_LOCAL_PENDING)
 
863
  if (type == TP_TUBE_TYPE_DBUS &&
 
864
      state != TP_TUBE_STATE_LOCAL_PENDING)
840
865
    {
841
866
      add_yourself_in_dbus_names (self, tube_id);
842
867
    }
843
 
#endif
844
868
 
845
869
  g_signal_connect (tube, "opened", G_CALLBACK (tube_opened_cb), self);
846
870
  g_signal_connect (tube, "closed", G_CALLBACK (tube_closed_cb), self);
847
871
 
848
872
  if (muc_connection != NULL)
849
873
    g_object_unref (muc_connection);
 
874
 
 
875
  return tube;
850
876
}
851
877
 
852
878
static gboolean
853
879
extract_tube_information (SalutTubesChannel *self,
854
880
                          GibberXmppNode *tube_node,
855
 
                          SalutTubeType *type,
 
881
                          TpTubeType *type,
856
882
                          TpHandle *initiator_handle,
857
883
                          const gchar **service,
858
884
                          GHashTable **parameters,
859
 
                          gboolean *offering,
860
885
                          guint *tube_id)
861
886
{
862
887
  SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
870
895
      _type = gibber_xmpp_node_get_attribute (tube_node, "type");
871
896
 
872
897
 
873
 
      /*
874
898
      if (!tp_strdiff (_type, "stream"))
875
899
        {
876
 
          *type = TP_TUBE_TYPE_STREAM_UNIX;
 
900
          *type = TP_TUBE_TYPE_STREAM;
877
901
        }
878
 
        */
879
 
      if (!tp_strdiff (_type, "dbus"))
 
902
      else if (!tp_strdiff (_type, "dbus"))
880
903
        {
881
 
          *type = SALUT_TUBE_TYPE_DBUS;
 
904
          *type = TP_TUBE_TYPE_DBUS;
882
905
        }
883
906
      else
884
907
        {
892
915
      const gchar *initiator;
893
916
 
894
917
      initiator = gibber_xmpp_node_get_attribute (tube_node, "initiator");
895
 
      *initiator_handle = tp_handle_ensure (contact_repo, initiator, NULL,
896
 
          NULL);
897
 
 
898
 
      if (*initiator_handle == 0)
899
 
        {
900
 
          DEBUG ("invalid initiator ID %s", initiator);
901
 
          return FALSE;
 
918
 
 
919
      if (initiator != NULL)
 
920
        {
 
921
          *initiator_handle = tp_handle_ensure (contact_repo, initiator, NULL,
 
922
              NULL);
 
923
 
 
924
          if (*initiator_handle == 0)
 
925
            {
 
926
              DEBUG ("invalid initiator ID %s", initiator);
 
927
              return FALSE;
 
928
            }
 
929
        }
 
930
      else
 
931
        {
 
932
          *initiator_handle = 0;
902
933
        }
903
934
    }
904
935
 
916
947
          "parameter");
917
948
    }
918
949
 
919
 
  if (offering != NULL)
920
 
    {
921
 
      const gchar *_offering;
922
 
 
923
 
      _offering = gibber_xmpp_node_get_attribute (tube_node, "offering");
924
 
      if (!tp_strdiff (_offering, "false"))
925
 
        *offering = FALSE;
926
 
      else
927
 
        *offering = TRUE;
928
 
    }
929
 
 
930
950
  if (tube_id != NULL)
931
951
    {
932
952
      const gchar *str;
977
997
  SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
978
998
  GibberXmppNode *parameters_node;
979
999
  GHashTable *parameters;
980
 
  SalutTubeType type;
 
1000
  TpTubeType type;
981
1001
  gchar *service, *id_str;
982
1002
  guint tube_id;
983
1003
  TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
984
1004
    (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
985
1005
  TpHandle initiator_handle;
986
 
  const gchar *initiator;
987
1006
 
988
1007
  g_object_get (G_OBJECT (tube),
 
1008
      "type", &type,
 
1009
      "initiator", &initiator_handle,
989
1010
      "service", &service,
990
1011
      "parameters", &parameters,
991
 
      "type", &type,
992
1012
      "id", &tube_id,
993
 
      "initiator", &initiator_handle,
994
1013
      NULL);
995
1014
 
996
1015
  id_str = g_strdup_printf ("%u", tube_id);
997
1016
 
998
1017
  gibber_xmpp_node_set_attribute (node, "service", service);
999
1018
  gibber_xmpp_node_set_attribute (node, "id", id_str);
1000
 
  initiator = tp_handle_inspect (contact_repo, initiator_handle);
1001
 
  gibber_xmpp_node_set_attribute (node, "initiator", initiator);
1002
1019
 
1003
1020
  g_free (id_str);
1004
1021
 
1005
1022
  switch (type)
1006
1023
    {
1007
 
      case SALUT_TUBE_TYPE_DBUS:
1008
 
        gibber_xmpp_node_set_attribute (node, "type", "dbus");
 
1024
      case TP_TUBE_TYPE_DBUS:
 
1025
        {
 
1026
          gchar *name, *stream_id;
 
1027
 
 
1028
          g_object_get (G_OBJECT (tube),
 
1029
              "dbus-name", &name,
 
1030
              "stream-id", &stream_id,
 
1031
              NULL);
 
1032
 
 
1033
          gibber_xmpp_node_set_attribute (node, "type", "dbus");
 
1034
          gibber_xmpp_node_set_attribute (node, "stream-id", stream_id);
 
1035
          gibber_xmpp_node_set_attribute (node, "initiator",
 
1036
              tp_handle_inspect (contact_repo, initiator_handle));
 
1037
 
 
1038
          if (name != NULL)
 
1039
            gibber_xmpp_node_set_attribute (node, "dbus-name", name);
 
1040
 
 
1041
          g_free (name);
 
1042
          g_free (stream_id);
 
1043
 
 
1044
        }
1009
1045
        break;
1010
 
        /*
1011
 
      case TP_TUBE_TYPE_STREAM_UNIX:
 
1046
      case TP_TUBE_TYPE_STREAM:
1012
1047
        gibber_xmpp_node_set_attribute (node, "type", "stream");
1013
1048
        break;
1014
 
        */
1015
1049
      default:
1016
1050
        g_assert_not_reached ();
1017
1051
    }
1018
1052
 
1019
 
  if (type == SALUT_TUBE_TYPE_DBUS)
1020
 
    {
1021
 
      gchar *name, *stream_id;
1022
 
 
1023
 
      g_object_get (G_OBJECT (tube),
1024
 
          "dbus-name", &name,
1025
 
          "stream-id", &stream_id,
1026
 
          NULL);
1027
 
 
1028
 
      gibber_xmpp_node_set_attribute (node, "dbus-name", name);
1029
 
      gibber_xmpp_node_set_attribute (node, "stream-id", stream_id);
1030
 
 
1031
 
      g_free (name);
1032
 
      g_free (stream_id);
1033
 
    }
1034
 
 
1035
1053
  parameters_node = gibber_xmpp_node_add_child (node, "parameters");
1036
1054
  salut_gibber_xmpp_node_add_children_from_properties (parameters_node,
1037
1055
      parameters, "parameter");
1054
1072
  SalutTubeIface *tube = (SalutTubeIface *) value;
1055
1073
  struct _i_hate_g_hash_table_foreach *data =
1056
1074
    (struct _i_hate_g_hash_table_foreach *) user_data;
1057
 
  SalutTubeState state;
 
1075
  SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (
 
1076
      data->self);
 
1077
  TpTubeState state;
1058
1078
  GibberXmppNode *tube_node;
 
1079
  TpTubeType type;
 
1080
  TpHandle initiator;
1059
1081
 
1060
1082
  if (tube == NULL)
1061
1083
    return;
1062
1084
 
1063
1085
  g_object_get (tube,
1064
 
                "state", &state,
1065
 
                NULL);
1066
 
 
1067
 
  if (state != SALUT_TUBE_STATE_OPEN)
 
1086
      "state", &state,
 
1087
      "type", &type,
 
1088
      "initiator", &initiator,
 
1089
      NULL);
 
1090
 
 
1091
  if (state != TP_TUBE_STATE_OPEN)
 
1092
    return;
 
1093
 
 
1094
  if (type == TP_TUBE_TYPE_STREAM && initiator != priv->self_handle)
 
1095
    /* We only announce stream tubes we initiated */
1068
1096
    return;
1069
1097
 
1070
1098
  tube_node = gibber_xmpp_node_add_child (data->tubes_node, "tube");
1072
1100
}
1073
1101
 
1074
1102
static gboolean
1075
 
update_tubes_info (SalutTubesChannel *self,
1076
 
                   gboolean request)
 
1103
update_tubes_info (SalutTubesChannel *self)
1077
1104
{
1078
1105
  SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
1079
1106
  TpBaseConnection *conn = (TpBaseConnection*) priv->conn;
1101
1128
  node = gibber_xmpp_node_get_child_ns (msg->node, "tubes",
1102
1129
      GIBBER_TELEPATHY_NS_TUBES);
1103
1130
 
1104
 
  if (request)
1105
 
    gibber_xmpp_node_set_attribute (node, "request", "true");
1106
 
 
1107
1131
  data.self = self;
1108
1132
  data.tubes_node = node;
1109
1133
 
1129
1153
  return g_random_int_range (0, G_MAXINT);
1130
1154
}
1131
1155
 
1132
 
/* XXX we should move that in some kind of bytestream factory */
1133
 
gchar *
1134
 
generate_stream_id (void)
1135
 
{
1136
 
  gchar *stream_id;
1137
 
 
1138
 
  stream_id = g_strdup_printf ("%lu-%u", (unsigned long) time (NULL),
1139
 
      g_random_int ());
1140
 
 
1141
 
  return stream_id;
1142
 
}
1143
 
 
1144
1156
/**
1145
1157
 * salut_tubes_channel_offer_d_bus_tube
1146
1158
 *
1148
1160
 * on org.freedesktop.Telepathy.Channel.Type.Tubes
1149
1161
 */
1150
1162
static void
1151
 
salut_tubes_channel_offer_tube (SalutSvcChannelTypeTubes *iface,
1152
 
                                guint type,
1153
 
                                const gchar *service,
1154
 
                                GHashTable *parameters,
1155
 
                                DBusGMethodInvocation *context)
1156
 
{
1157
 
#ifdef HAVE_DBUS_TUBE
1158
 
  SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
1159
 
  SalutTubesChannelPrivate *priv;
1160
 
  TpBaseConnection *base;
1161
 
  guint tube_id;
1162
 
  SalutTubeIface *tube;
1163
 
  GHashTable *parameters_copied;
1164
 
  gchar *stream_id;
1165
 
 
1166
 
  g_assert (SALUT_IS_TUBES_CHANNEL (self));
1167
 
 
1168
 
  priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
1169
 
  base = (TpBaseConnection*) priv->conn;
1170
 
 
1171
 
   if (type != SALUT_TUBE_TYPE_DBUS)
1172
 
    {
1173
 
      GError *error = g_error_new (TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
1174
 
          "invalid type: %d", type);
1175
 
 
1176
 
      dbus_g_method_return_error (context, error);
1177
 
      g_error_free (error);
1178
 
 
1179
 
      return;
1180
 
    }
1181
 
 
1182
 
  parameters_copied = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
1183
 
      (GDestroyNotify) tp_g_value_slice_free);
1184
 
  g_hash_table_foreach (parameters, copy_parameter, parameters_copied);
1185
 
 
1186
 
  stream_id = generate_stream_id ();
1187
 
  tube_id = generate_tube_id ();
1188
 
 
1189
 
  create_new_tube (self, SALUT_TUBE_TYPE_DBUS, priv->self_handle,
1190
 
      service, parameters_copied, (const gchar*) stream_id, tube_id);
1191
 
 
1192
 
  tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
1193
 
 
1194
 
  salut_svc_channel_type_tubes_return_from_offer_tube (context, tube_id);
1195
 
 
1196
 
  g_free (stream_id);
1197
 
#else
1198
 
  GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
1199
 
      "D-Bus tube support not built" };
1200
 
 
1201
 
  dbus_g_method_return_error (context, &error);
1202
 
  return;
1203
 
#endif
1204
 
}
1205
 
 
1206
 
/**
1207
 
 * salut_tubes_channel_offer_stream_unix_tube
1208
 
 *
1209
 
 * Implements D-Bus method OfferStreamUnixTube
1210
 
 * on org.freedesktop.Telepathy.Channel.Type.Tubes
1211
 
 */
1212
 
#if 0
1213
 
static void
1214
 
salut_tubes_channel_offer_stream_unix_tube (SalutSvcChannelTypeTubes *iface,
1215
 
                                             const gchar *service,
1216
 
                                             const gchar *socket,
1217
 
                                             GHashTable *parameters,
1218
 
                                             DBusGMethodInvocation *context)
1219
 
{
1220
 
  GError error = { TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
1221
 
      "Stream Unix tube not implemented" };
1222
 
 
1223
 
  dbus_g_method_return_error (context, &error);
1224
 
  return;
1225
 
  SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
1226
 
  SalutTubesChannelPrivate *priv;
1227
 
  TpBaseConnection *base;
1228
 
  guint tube_id;
1229
 
  SalutTubeIface *tube;
1230
 
  GHashTable *parameters_copied;
1231
 
  gchar *stream_id;
1232
 
  struct stat stat_buff;
1233
 
 
1234
 
  g_assert (SALUT_IS_TUBES_CHANNEL (self));
1235
 
 
1236
 
  priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
1237
 
  base = (TpBaseConnection*) priv->conn;
1238
 
 
1239
 
  if (g_stat (socket, &stat_buff) == -1)
1240
 
    {
1241
 
      GError *error = NULL;
1242
 
 
1243
 
      DEBUG ("Error calling stat on socket: %s", g_strerror (errno));
1244
 
 
1245
 
      error = g_error_new (TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, "%s: %s",
1246
 
          socket, g_strerror (errno));
1247
 
 
1248
 
      dbus_g_method_return_error (context, error);
1249
 
 
1250
 
      g_error_free (error);
1251
 
      return;
1252
 
    }
1253
 
 
1254
 
  if (!S_ISSOCK (stat_buff.st_mode))
1255
 
    {
1256
 
      GError *error = NULL;
1257
 
 
1258
 
      DEBUG ("%s is not a socket", socket);
1259
 
 
1260
 
      error = g_error_new (TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
1261
 
          "%s is not a socket", socket);
1262
 
 
1263
 
      dbus_g_method_return_error (context, error);
1264
 
 
1265
 
      g_error_free (error);
1266
 
      return;
1267
 
    }
1268
 
 
1269
 
  parameters_copied = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
1270
 
      (GDestroyNotify) tp_g_value_slice_free);
1271
 
  g_hash_table_foreach (parameters, copy_parameter, parameters_copied);
1272
 
 
1273
 
  stream_id = salut_bytestream_factory_generate_stream_id ();
1274
 
  tube_id = generate_tube_id ();
1275
 
 
1276
 
  create_new_tube (self, TP_TUBE_TYPE_STREAM_UNIX, priv->self_handle,
1277
 
      service, parameters_copied, (const gchar*) stream_id, tube_id);
1278
 
 
1279
 
  tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
1280
 
 
1281
 
  g_object_set (tube, "socket", socket, NULL);
1282
 
 
1283
 
  if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
1284
 
    {
1285
 
      /* Stream initiation */
1286
 
      GError *error = NULL;
1287
 
 
1288
 
      if (!start_stream_initiation (self, tube, stream_id, &error))
1289
 
        {
1290
 
          salut_tube_iface_close (tube);
1291
 
 
1292
 
          dbus_g_method_return_error (context, error);
1293
 
 
1294
 
          g_error_free (error);
1295
 
          g_free (stream_id);
1296
 
          return;
1297
 
        }
1298
 
    }
1299
 
 
1300
 
  g_signal_connect (tube, "new-connection",
1301
 
      G_CALLBACK (stream_unix_tube_new_connection_cb), self);
 
1163
salut_tubes_channel_offer_d_bus_tube (TpSvcChannelTypeTubes *iface,
 
1164
                                      const gchar *service,
 
1165
                                      GHashTable *parameters,
 
1166
                                      DBusGMethodInvocation *context)
 
1167
{
 
1168
  SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
 
1169
  SalutTubesChannelPrivate *priv;
 
1170
  TpBaseConnection *base;
 
1171
  guint tube_id;
 
1172
  SalutTubeIface *tube;
 
1173
  GHashTable *parameters_copied;
 
1174
 
 
1175
  g_assert (SALUT_IS_TUBES_CHANNEL (self));
 
1176
 
 
1177
  priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
 
1178
  base = (TpBaseConnection*) priv->conn;
 
1179
 
 
1180
  if (priv->handle_type == TP_HANDLE_TYPE_ROOM
 
1181
    && !tp_handle_set_is_member (TP_GROUP_MIXIN(self->muc)->members,
 
1182
        priv->self_handle))
 
1183
    {
 
1184
      GError error = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
 
1185
         "Tube channel isn't connected" };
 
1186
 
 
1187
      dbus_g_method_return_error (context, &error);
 
1188
      return;
 
1189
    }
 
1190
 
 
1191
  parameters_copied = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
 
1192
      (GDestroyNotify) tp_g_value_slice_free);
 
1193
  g_hash_table_foreach (parameters, copy_parameter, parameters_copied);
 
1194
 
 
1195
  tube_id = generate_tube_id ();
 
1196
 
 
1197
  tube = create_new_tube (self, TP_TUBE_TYPE_DBUS, priv->self_handle,
 
1198
      service, parameters_copied, tube_id, NULL);
1302
1199
 
1303
1200
  tp_svc_channel_type_tubes_return_from_offer_d_bus_tube (context, tube_id);
1304
 
 
1305
 
  g_free (stream_id);
1306
1201
}
1307
 
#endif
1308
1202
 
1309
1203
/**
1310
 
 * salut_tubes_channel_accept_tube
 
1204
 * salut_tubes_channel_accept_d_bus_tube
1311
1205
 *
1312
 
 * Implements D-Bus method AcceptTube
 
1206
 * Implements D-Bus method AcceptDBusTube
1313
1207
 * on org.freedesktop.Telepathy.Channel.Type.Tubes
1314
1208
 */
1315
1209
static void
1316
 
salut_tubes_channel_accept_tube (SalutSvcChannelTypeTubes *iface,
1317
 
                                  guint id,
1318
 
                                  DBusGMethodInvocation *context)
 
1210
salut_tubes_channel_accept_d_bus_tube (TpSvcChannelTypeTubes *iface,
 
1211
                                       guint id,
 
1212
                                       DBusGMethodInvocation *context)
1319
1213
{
1320
1214
  SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
1321
1215
  SalutTubesChannelPrivate *priv;
1322
1216
  SalutTubeIface *tube;
1323
 
  SalutTubeState state;
1324
 
  SalutTubeType type;
 
1217
  TpTubeState state;
 
1218
  TpTubeType type;
 
1219
  gchar *addr;
1325
1220
 
1326
1221
  g_assert (SALUT_IS_TUBES_CHANNEL (self));
1327
1222
 
1337
1232
      return;
1338
1233
    }
1339
1234
 
1340
 
  g_object_get (tube, "state", &state, NULL);
1341
 
  if (state != SALUT_TUBE_STATE_LOCAL_PENDING)
1342
 
    {
1343
 
      /* XXX raise an error if the tube was not in the local pending state ? */
1344
 
      salut_svc_channel_type_tubes_return_from_accept_tube (context);
1345
 
      return;
1346
 
    }
1347
 
 
1348
 
  salut_tube_iface_accept (tube);
1349
 
 
1350
 
  update_tubes_info (self, FALSE);
1351
 
 
1352
 
  g_object_get (tube, "type", &type, NULL);
1353
 
 
1354
 
#ifdef HAVE_DBUS_TUBE
1355
 
  if (type == SALUT_TUBE_TYPE_DBUS)
1356
 
    {
1357
 
      add_yourself_in_dbus_names (self, id);
1358
 
    }
1359
 
#endif
1360
 
 
1361
 
  salut_svc_channel_type_tubes_return_from_accept_tube (context);
 
1235
  g_object_get (tube,
 
1236
      "type", &type,
 
1237
      "state", &state,
 
1238
      NULL);
 
1239
 
 
1240
  if (type != TP_TUBE_TYPE_DBUS)
 
1241
    {
 
1242
      GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
 
1243
          "Tube is not a D-Bus tube" };
 
1244
 
 
1245
      dbus_g_method_return_error (context, &error);
 
1246
      return;
 
1247
    }
 
1248
 
 
1249
  if (state != TP_TUBE_STATE_LOCAL_PENDING)
 
1250
    {
 
1251
      GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
 
1252
          "Tube is not in the local pending state" };
 
1253
 
 
1254
      dbus_g_method_return_error (context, &error);
 
1255
 
 
1256
      return;
 
1257
    }
 
1258
 
 
1259
  salut_tube_iface_accept (tube, NULL);
 
1260
 
 
1261
  update_tubes_info (self);
 
1262
 
 
1263
  g_object_get (tube,
 
1264
      "dbus-address", &addr,
 
1265
      NULL);
 
1266
 
 
1267
  add_yourself_in_dbus_names (self, id);
 
1268
 
 
1269
  tp_svc_channel_type_tubes_return_from_accept_d_bus_tube (context, addr);
 
1270
  g_free (addr);
1362
1271
}
1363
1272
 
1364
1273
/**
1368
1277
 * on org.freedesktop.Telepathy.Channel.Type.Tubes
1369
1278
 */
1370
1279
static void
1371
 
salut_tubes_channel_close_tube (SalutSvcChannelTypeTubes *iface,
 
1280
salut_tubes_channel_close_tube (TpSvcChannelTypeTubes *iface,
1372
1281
                                 guint id,
1373
1282
                                 DBusGMethodInvocation *context)
1374
1283
{
1391
1300
 
1392
1301
  salut_tube_iface_close (tube);
1393
1302
 
1394
 
  salut_svc_channel_type_tubes_return_from_close_tube (context);
 
1303
  tp_svc_channel_type_tubes_return_from_close_tube (context);
1395
1304
}
1396
1305
 
1397
1306
/**
1398
 
 * salut_tubes_channel_get_d_bus_server_address
 
1307
 * salut_tubes_channel_get_d_bus_tube_address
1399
1308
 *
1400
 
 * Implements D-Bus method GetDBusServerAddress
 
1309
 * Implements D-Bus method GetDBusTubeAddress
1401
1310
 * on org.freedesktop.Telepathy.Channel.Type.Tubes
1402
1311
 */
1403
1312
static void
1404
 
salut_tubes_channel_get_d_bus_server_address (SalutSvcChannelTypeTubes *iface,
1405
 
                                               guint id,
1406
 
                                               DBusGMethodInvocation *context)
 
1313
salut_tubes_channel_get_d_bus_tube_address (TpSvcChannelTypeTubes *iface,
 
1314
                                            guint id,
 
1315
                                            DBusGMethodInvocation *context)
1407
1316
{
1408
 
#ifdef HAVE_DBUS_TUBE
1409
1317
  SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
1410
1318
  SalutTubesChannelPrivate *priv;
1411
1319
  SalutTubeIface *tube;
1412
1320
  gchar *addr;
1413
 
  SalutTubeType type;
1414
 
  SalutTubeState state;
 
1321
  TpTubeType type;
 
1322
  TpTubeState state;
1415
1323
 
1416
1324
  g_assert (SALUT_IS_TUBES_CHANNEL (self));
1417
1325
 
1432
1340
      "state", &state,
1433
1341
      NULL);
1434
1342
 
1435
 
  if (type != SALUT_TUBE_TYPE_DBUS)
 
1343
  if (type != TP_TUBE_TYPE_DBUS)
1436
1344
    {
1437
1345
      GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
1438
1346
          "Tube is not a D-Bus tube" };
1441
1349
      return;
1442
1350
    }
1443
1351
 
1444
 
  if (state != SALUT_TUBE_STATE_OPEN)
 
1352
  if (state != TP_TUBE_STATE_OPEN)
1445
1353
    {
1446
1354
      GError error = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
1447
1355
          "Tube is not open" };
1451
1359
    }
1452
1360
 
1453
1361
  g_object_get (tube, "dbus-address", &addr, NULL);
1454
 
  salut_svc_channel_type_tubes_return_from_get_d_bus_server_address (context,
 
1362
  tp_svc_channel_type_tubes_return_from_get_d_bus_tube_address (context,
1455
1363
      addr);
1456
1364
  g_free (addr);
1457
 
 
1458
 
#else /* ! HAVE_DBUS_TUBE */
1459
 
 
1460
 
  GError error = { TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
1461
 
      "D-Bus tube support not built" };
1462
 
 
1463
 
  dbus_g_method_return_error (context, &error);
1464
 
#endif
1465
1365
}
1466
1366
 
1467
 
#ifdef HAVE_DBUS_TUBE
1468
1367
static void
1469
1368
get_d_bus_names_foreach (gpointer key,
1470
1369
                         gpointer value,
1482
1381
      G_MAXUINT);
1483
1382
  g_ptr_array_add (ret, g_value_get_boxed (&tmp));
1484
1383
}
1485
 
#endif
1486
1384
 
1487
1385
/**
1488
1386
 * salut_tubes_channel_get_d_bus_names
1491
1389
 * on org.freedesktop.Telepathy.Channel.Type.Tubes
1492
1390
 */
1493
1391
static void
1494
 
salut_tubes_channel_get_d_bus_names (SalutSvcChannelTypeTubes *iface,
 
1392
salut_tubes_channel_get_d_bus_names (TpSvcChannelTypeTubes *iface,
1495
1393
                                      guint id,
1496
1394
                                      DBusGMethodInvocation *context)
1497
1395
{
1498
 
#ifdef HAVE_DBUS_TUBE
1499
1396
  SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
1500
1397
  SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
1501
1398
  SalutTubeIface *tube;
1502
1399
  GHashTable *names;
1503
1400
  GPtrArray *ret;
1504
 
  SalutTubeType type;
1505
 
  SalutTubeState state;
 
1401
  TpTubeType type;
 
1402
  TpTubeState state;
1506
1403
  guint i;
1507
1404
 
1508
1405
  g_assert (SALUT_IS_TUBES_CHANNEL (self));
1522
1419
      "state", &state,
1523
1420
      NULL);
1524
1421
 
1525
 
  if (type != SALUT_TUBE_TYPE_DBUS)
 
1422
  if (type != TP_TUBE_TYPE_DBUS)
1526
1423
    {
1527
1424
      GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
1528
1425
          "Tube is not a D-Bus tube" };
1531
1428
      return;
1532
1429
    }
1533
1430
 
1534
 
  if (state != SALUT_TUBE_STATE_OPEN)
 
1431
  if (state != TP_TUBE_STATE_OPEN)
1535
1432
    {
1536
1433
      GError error = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
1537
1434
          "Tube is not open" };
1546
1443
  ret = g_ptr_array_sized_new (g_hash_table_size (names));
1547
1444
  g_hash_table_foreach (names, get_d_bus_names_foreach, ret);
1548
1445
 
1549
 
  salut_svc_channel_type_tubes_return_from_get_d_bus_names (context, ret);
 
1446
  tp_svc_channel_type_tubes_return_from_get_d_bus_names (context, ret);
1550
1447
 
1551
1448
  for (i = 0; i < ret->len; i++)
1552
1449
    g_boxed_free (DBUS_NAME_PAIR_TYPE, ret->pdata[i]);
1553
1450
  g_hash_table_unref (names);
1554
1451
  g_ptr_array_free (ret, TRUE);
1555
 
 
1556
 
#else /* HAVE_DBUS_TUBE */
1557
 
 
1558
 
  GError error = { TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
1559
 
      "D-Bus tube support not built" };
1560
 
 
1561
 
  dbus_g_method_return_error (context, &error);
1562
 
#endif
1563
 
}
1564
 
 
1565
 
/**
1566
 
 * salut_tubes_channel_get_stream_unix_socket_address
1567
 
 *
1568
 
 * Implements D-Bus method GetStreamSocketAddress
1569
 
 * on org.freedesktop.Telepathy.Channel.Type.Tubes
1570
 
 */
1571
 
#if 0
1572
 
static void
1573
 
salut_tubes_channel_get_stream_unix_socket_address (SalutSvcChannelTypeTubes *iface,
 
1452
}
 
1453
 
 
1454
static void
 
1455
stream_tube_new_connection_cb (SalutTubeIface *tube,
 
1456
                               guint contact,
 
1457
                               gpointer user_data)
 
1458
{
 
1459
  SalutTubesChannel *self = SALUT_TUBES_CHANNEL (user_data);
 
1460
  guint tube_id;
 
1461
  TpTubeType type;
 
1462
 
 
1463
  g_object_get (tube,
 
1464
      "id", &tube_id,
 
1465
      "type", &type,
 
1466
      NULL);
 
1467
 
 
1468
  g_assert (type == TP_TUBE_TYPE_STREAM);
 
1469
 
 
1470
  tp_svc_channel_type_tubes_emit_stream_tube_new_connection (self,
 
1471
      tube_id, contact);
 
1472
}
 
1473
 
 
1474
/**
 
1475
 * salut_tubes_channel_offer_stream_tube
 
1476
 *
 
1477
 * Implements D-Bus method OfferStreamTube
 
1478
 * on org.freedesktop.Telepathy.Channel.Type.Tubes
 
1479
 */
 
1480
static void
 
1481
salut_tubes_channel_offer_stream_tube (TpSvcChannelTypeTubes *iface,
 
1482
                                        const gchar *service,
 
1483
                                        GHashTable *parameters,
 
1484
                                        guint address_type,
 
1485
                                        const GValue *address,
 
1486
                                        guint access_control,
 
1487
                                        const GValue *access_control_param,
 
1488
                                        DBusGMethodInvocation *context)
 
1489
{
 
1490
  SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
 
1491
  SalutTubesChannelPrivate *priv;
 
1492
  TpBaseConnection *base;
 
1493
  guint tube_id;
 
1494
  SalutTubeIface *tube;
 
1495
  GHashTable *parameters_copied;
 
1496
  GError *error = NULL;
 
1497
 
 
1498
  priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
 
1499
  base = (TpBaseConnection*) priv->conn;
 
1500
 
 
1501
  if (priv->handle_type == TP_HANDLE_TYPE_ROOM
 
1502
    && !tp_handle_set_is_member (TP_GROUP_MIXIN(self->muc)->members,
 
1503
        priv->self_handle))
 
1504
    {
 
1505
      GError error = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
 
1506
         "Tube channel isn't connected" };
 
1507
 
 
1508
      dbus_g_method_return_error (context, &error);
 
1509
      return;
 
1510
    }
 
1511
 
 
1512
  if (!salut_tube_stream_check_params (address_type, address,
 
1513
        access_control, access_control_param, &error))
 
1514
    {
 
1515
      dbus_g_method_return_error (context, error);
 
1516
      g_error_free (error);
 
1517
      return;
 
1518
    }
 
1519
 
 
1520
  parameters_copied = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
 
1521
      (GDestroyNotify) tp_g_value_slice_free);
 
1522
  g_hash_table_foreach (parameters, copy_parameter, parameters_copied);
 
1523
 
 
1524
  tube_id = generate_tube_id ();
 
1525
 
 
1526
  tube = create_new_tube (self, TP_TUBE_TYPE_STREAM, priv->self_handle,
 
1527
      service, parameters_copied, tube_id, NULL);
 
1528
 
 
1529
  g_object_set (tube,
 
1530
      "address-type", address_type,
 
1531
      "address", address,
 
1532
      "access-control", access_control,
 
1533
      "access-control-param", access_control_param,
 
1534
      NULL);
 
1535
 
 
1536
  g_signal_connect (tube, "new-connection",
 
1537
      G_CALLBACK (stream_tube_new_connection_cb), self);
 
1538
 
 
1539
  tp_svc_channel_type_tubes_return_from_offer_stream_tube (context,
 
1540
      tube_id);
 
1541
}
 
1542
 
 
1543
/**
 
1544
 * salut_tubes_channel_accept_stream_tube
 
1545
 *
 
1546
 * Implements D-Bus method AcceptStreamTube
 
1547
 * on org.freedesktop.Telepathy.Channel.Type.Tubes
 
1548
 */
 
1549
static void
 
1550
salut_tubes_channel_accept_stream_tube (TpSvcChannelTypeTubes *iface,
 
1551
                                        guint id,
 
1552
                                        guint address_type,
 
1553
                                        guint access_control,
 
1554
                                        const GValue *access_control_param,
 
1555
                                        DBusGMethodInvocation *context)
 
1556
{
 
1557
  SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
 
1558
  SalutTubesChannelPrivate *priv;
 
1559
  SalutTubeIface *tube;
 
1560
  TpTubeState state;
 
1561
  TpTubeType type;
 
1562
  GValue *address;
 
1563
  GError *error = NULL;
 
1564
 
 
1565
  g_assert (SALUT_IS_TUBES_CHANNEL (self));
 
1566
 
 
1567
  priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
 
1568
 
 
1569
  tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (id));
 
1570
  if (tube == NULL)
 
1571
    {
 
1572
      GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, "Unknown tube" };
 
1573
 
 
1574
      dbus_g_method_return_error (context, &error);
 
1575
      return;
 
1576
    }
 
1577
 
 
1578
  if (address_type != TP_SOCKET_ADDRESS_TYPE_UNIX &&
 
1579
      address_type != TP_SOCKET_ADDRESS_TYPE_IPV4 &&
 
1580
      address_type != TP_SOCKET_ADDRESS_TYPE_IPV6)
 
1581
    {
 
1582
      GError *error = NULL;
 
1583
 
 
1584
      error = g_error_new (TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
 
1585
          "Address type %d not implemented", address_type);
 
1586
 
 
1587
      dbus_g_method_return_error (context, error);
 
1588
 
 
1589
      g_error_free (error);
 
1590
      return;
 
1591
    }
 
1592
 
 
1593
  if (access_control != TP_SOCKET_ACCESS_CONTROL_LOCALHOST)
 
1594
    {
 
1595
      GError *error = NULL;
 
1596
 
 
1597
      error = g_error_new (TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
 
1598
          "Unix sockets only support localhost control access");
 
1599
 
 
1600
      dbus_g_method_return_error (context, error);
 
1601
 
 
1602
      g_error_free (error);
 
1603
      return;
 
1604
    }
 
1605
 
 
1606
  g_object_get (tube,
 
1607
      "type", &type,
 
1608
      "state", &state,
 
1609
      NULL);
 
1610
 
 
1611
  if (type != TP_TUBE_TYPE_STREAM)
 
1612
    {
 
1613
      GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
 
1614
          "Tube is not a stream tube" };
 
1615
 
 
1616
      dbus_g_method_return_error (context, &error);
 
1617
      return;
 
1618
    }
 
1619
 
 
1620
  if (state != TP_TUBE_STATE_LOCAL_PENDING)
 
1621
    {
 
1622
      GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
 
1623
          "Tube is not in the local pending state" };
 
1624
 
 
1625
      dbus_g_method_return_error (context, &error);
 
1626
      return;
 
1627
    }
 
1628
 
 
1629
  g_object_set (tube,
 
1630
      "address-type", address_type,
 
1631
      "access-control", access_control,
 
1632
      "access-control-param", access_control_param,
 
1633
      NULL);
 
1634
 
 
1635
  if (!salut_tube_iface_accept (tube, &error))
 
1636
    {
 
1637
      dbus_g_method_return_error (context, error);
 
1638
      return;
 
1639
    }
 
1640
 
 
1641
  update_tubes_info (self);
 
1642
 
 
1643
  g_object_get (tube, "address", &address, NULL);
 
1644
 
 
1645
  tp_svc_channel_type_tubes_return_from_accept_stream_tube (context,
 
1646
      address);
 
1647
}
 
1648
 
 
1649
/**
 
1650
 * salut_tubes_channel_get_stream_tube_socket_address
 
1651
 *
 
1652
 * Implements D-Bus method GetStreamTubeSocketAddress
 
1653
 * on org.freedesktop.Telepathy.Channel.Type.Tubes
 
1654
 */
 
1655
static void
 
1656
salut_tubes_channel_get_stream_tube_socket_address (TpSvcChannelTypeTubes *iface,
1574
1657
                                                    guint id,
1575
1658
                                                    DBusGMethodInvocation *context)
1576
1659
{
1577
1660
  SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
1578
1661
  SalutTubesChannelPrivate *priv  = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
1579
1662
  SalutTubeIface *tube;
1580
 
  SalutTubeType type;
1581
 
  SalutTubeState state;
1582
 
  gchar *socket;
 
1663
  TpTubeType type;
 
1664
  TpTubeState state;
 
1665
  GValue *address;
 
1666
  TpSocketAddressType address_type;
1583
1667
 
1584
1668
  tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (id));
1585
1669
  if (tube == NULL)
1595
1679
      "state", &state,
1596
1680
      NULL);
1597
1681
 
1598
 
  if (type != TP_TUBE_TYPE_STREAM_UNIX)
 
1682
  if (type != TP_TUBE_TYPE_STREAM)
1599
1683
    {
1600
1684
      GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
1601
1685
          "Tube is not a Stream tube" };
1604
1688
      return;
1605
1689
    }
1606
1690
 
1607
 
  if (state != SALUT_TUBE_STATE_OPEN)
 
1691
  if (state != TP_TUBE_STATE_OPEN)
1608
1692
    {
1609
1693
      GError error = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
1610
1694
          "Tube is not open" };
1614
1698
    }
1615
1699
 
1616
1700
  g_object_get (tube,
1617
 
      "socket", &socket,
 
1701
      "address", &address,
 
1702
      "address-type", &address_type,
1618
1703
      NULL);
1619
1704
 
1620
 
  tp_svc_channel_type_tubes_return_from_get_stream_unix_socket_address (
1621
 
      context, socket);
1622
 
 
1623
 
  g_free (socket);
1624
 
}
1625
 
#endif
 
1705
  tp_svc_channel_type_tubes_return_from_get_stream_tube_socket_address (
 
1706
      context, address_type, address);
 
1707
}
 
1708
 
 
1709
/**
 
1710
 * salut_tubes_channel_get_available_stream_tube_types
 
1711
 *
 
1712
 * Implements D-Bus method GetAvailableStreamTubeTypes
 
1713
 * on org.freedesktop.Telepathy.Channel.Type.Tubes
 
1714
 */
 
1715
static void
 
1716
salut_tubes_channel_get_available_stream_tube_types (
 
1717
    TpSvcChannelTypeTubes *iface,
 
1718
    DBusGMethodInvocation *context)
 
1719
{
 
1720
  GHashTable *ret;
 
1721
  GArray *unix_tab, *ipv4_tab, *ipv6_tab;
 
1722
  TpSocketAccessControl access;
 
1723
 
 
1724
  ret = g_hash_table_new (g_direct_hash, g_direct_equal);
 
1725
 
 
1726
  /* Socket_Address_Type_Unix */
 
1727
  unix_tab = g_array_sized_new (FALSE, FALSE, sizeof (TpSocketAccessControl),
 
1728
      1);
 
1729
  access = TP_SOCKET_ACCESS_CONTROL_LOCALHOST;
 
1730
  g_array_append_val (unix_tab, access);
 
1731
  g_hash_table_insert (ret, GUINT_TO_POINTER (TP_SOCKET_ADDRESS_TYPE_UNIX),
 
1732
      unix_tab);
 
1733
 
 
1734
  /* Socket_Address_Type_IPv4 */
 
1735
  ipv4_tab = g_array_sized_new (FALSE, FALSE, sizeof (TpSocketAccessControl),
 
1736
      1);
 
1737
  access = TP_SOCKET_ACCESS_CONTROL_LOCALHOST;
 
1738
  g_array_append_val (ipv4_tab, access);
 
1739
  g_hash_table_insert (ret, GUINT_TO_POINTER (TP_SOCKET_ADDRESS_TYPE_IPV4),
 
1740
      ipv4_tab);
 
1741
 
 
1742
  /* Socket_Address_Type_IPv6 */
 
1743
  ipv6_tab = g_array_sized_new (FALSE, FALSE, sizeof (TpSocketAccessControl),
 
1744
      1);
 
1745
  access = TP_SOCKET_ACCESS_CONTROL_LOCALHOST;
 
1746
  g_array_append_val (ipv6_tab, access);
 
1747
  g_hash_table_insert (ret, GUINT_TO_POINTER (TP_SOCKET_ADDRESS_TYPE_IPV6),
 
1748
      ipv6_tab);
 
1749
 
 
1750
  tp_svc_channel_type_tubes_return_from_get_available_stream_tube_types (
 
1751
      context, ret);
 
1752
 
 
1753
  g_array_free (unix_tab, TRUE);
 
1754
  g_array_free (ipv4_tab, TRUE);
 
1755
  g_array_free (ipv6_tab, TRUE);
 
1756
  g_hash_table_destroy (ret);
 
1757
}
1626
1758
 
1627
1759
static void salut_tubes_channel_dispose (GObject *object);
1628
1760
static void salut_tubes_channel_finalize (GObject *object);
1707
1839
 
1708
1840
  salut_tubes_channel_close (self);
1709
1841
 
1710
 
  /*
1711
 
  g_object_unref (priv->contact);
1712
 
  priv->contact = NULL;
1713
 
  */
1714
 
 
1715
1842
  if (G_OBJECT_CLASS (salut_tubes_channel_parent_class)->dispose)
1716
1843
    G_OBJECT_CLASS (salut_tubes_channel_parent_class)->dispose (object);
1717
1844
}
1735
1862
  guint id = GPOINTER_TO_UINT (key);
1736
1863
  SalutTubesChannel *self = (SalutTubesChannel *) user_data;
1737
1864
 
1738
 
  salut_svc_channel_type_tubes_emit_tube_closed (self, id);
 
1865
  tp_svc_channel_type_tubes_emit_tube_closed (self, id);
1739
1866
}
1740
1867
 
1741
1868
void
1793
1920
                                      DBusGMethodInvocation *context)
1794
1921
{
1795
1922
  tp_svc_channel_return_from_get_channel_type (context,
1796
 
      SALUT_IFACE_CHANNEL_TYPE_TUBES);
 
1923
      TP_IFACE_CHANNEL_TYPE_TUBES);
1797
1924
}
1798
1925
 
1799
1926
 
1844
1971
    }
1845
1972
}
1846
1973
 
 
1974
/* Called when we receive a SI request,
 
1975
 * via either salut_muc_manager_handle_si_stream_request or
 
1976
 * salut_tubes_manager_handle_si_stream_request
 
1977
 */
 
1978
void
 
1979
salut_tubes_channel_bytestream_offered (SalutTubesChannel *self,
 
1980
                                        GibberBytestreamIface *bytestream,
 
1981
                                        GibberXmppStanza *msg)
 
1982
{
 
1983
  SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
 
1984
  const gchar *stream_id, *tmp;
 
1985
  gchar *endptr;
 
1986
  GibberXmppNode *si_node, *stream_node;
 
1987
  guint tube_id;
 
1988
  unsigned long tube_id_tmp;
 
1989
  SalutTubeIface *tube;
 
1990
  GibberStanzaType type;
 
1991
  GibberStanzaSubType sub_type;
 
1992
 
 
1993
  /* Caller is expected to have checked that we have a stream or muc-stream
 
1994
   * node with a stream ID and the TUBES profile
 
1995
   */
 
1996
  gibber_xmpp_stanza_get_type_info (msg, &type, &sub_type);
 
1997
  g_return_if_fail (type == GIBBER_STANZA_TYPE_IQ);
 
1998
  g_return_if_fail (sub_type == GIBBER_STANZA_SUB_TYPE_SET);
 
1999
 
 
2000
  si_node = gibber_xmpp_node_get_child_ns (msg->node, "si",
 
2001
      GIBBER_XMPP_NS_SI);
 
2002
  g_return_if_fail (si_node != NULL);
 
2003
 
 
2004
  if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
 
2005
    stream_node = gibber_xmpp_node_get_child_ns (si_node,
 
2006
        "stream", GIBBER_TELEPATHY_NS_TUBES);
 
2007
  else
 
2008
    stream_node = gibber_xmpp_node_get_child_ns (si_node,
 
2009
        "muc-stream", GIBBER_TELEPATHY_NS_TUBES);
 
2010
  g_return_if_fail (stream_node != NULL);
 
2011
 
 
2012
  stream_id = gibber_xmpp_node_get_attribute (si_node, "id");
 
2013
  g_return_if_fail (stream_id != NULL);
 
2014
 
 
2015
  tmp = gibber_xmpp_node_get_attribute (stream_node, "tube");
 
2016
  if (tmp == NULL)
 
2017
    {
 
2018
      GError e = { GIBBER_XMPP_ERROR, XMPP_ERROR_BAD_REQUEST,
 
2019
          "<stream> or <muc-stream> has no tube attribute" };
 
2020
 
 
2021
      DEBUG ("%s", e.message);
 
2022
      gibber_bytestream_iface_close (bytestream, &e);
 
2023
      return;
 
2024
    }
 
2025
  tube_id_tmp = strtoul (tmp, &endptr, 10);
 
2026
  if (!endptr || *endptr || tube_id_tmp > G_MAXUINT32)
 
2027
    {
 
2028
      GError e = { GIBBER_XMPP_ERROR, XMPP_ERROR_BAD_REQUEST,
 
2029
          "<stream> or <muc-stream> tube attribute not numeric or > 2**32" };
 
2030
 
 
2031
      DEBUG ("tube id is not numeric or > 2**32: %s", tmp);
 
2032
      gibber_bytestream_iface_close (bytestream, &e);
 
2033
      return;
 
2034
    }
 
2035
  tube_id = (guint) tube_id_tmp;
 
2036
 
 
2037
  tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
 
2038
  if (tube == NULL)
 
2039
    {
 
2040
      GError e = { GIBBER_XMPP_ERROR, XMPP_ERROR_BAD_REQUEST,
 
2041
          "<stream> or <muc-stream> tube attribute points to a nonexistent "
 
2042
          "tube" };
 
2043
 
 
2044
      DEBUG ("tube %u doesn't exist", tube_id);
 
2045
      gibber_bytestream_iface_close (bytestream, &e);
 
2046
      return;
 
2047
    }
 
2048
 
 
2049
  DEBUG ("received new bytestream request for existing tube: %u", tube_id);
 
2050
 
 
2051
  salut_tube_iface_add_bytestream (tube, bytestream);
 
2052
}
 
2053
 
1847
2054
static void
1848
2055
tubes_iface_init (gpointer g_iface,
1849
2056
                  gpointer iface_data)
1850
2057
{
1851
 
  SalutSvcChannelTypeTubesClass *klass = (SalutSvcChannelTypeTubesClass *)g_iface;
 
2058
  TpSvcChannelTypeTubesClass *klass = (TpSvcChannelTypeTubesClass *) g_iface;
1852
2059
 
1853
 
#define IMPLEMENT(x) salut_svc_channel_type_tubes_implement_##x (\
 
2060
#define IMPLEMENT(x) tp_svc_channel_type_tubes_implement_##x (\
1854
2061
    klass, salut_tubes_channel_##x)
1855
2062
  IMPLEMENT(get_available_tube_types);
1856
2063
  IMPLEMENT(list_tubes);
1857
 
  IMPLEMENT(offer_tube);
1858
 
  /*
 
2064
  IMPLEMENT(close_tube);
1859
2065
  IMPLEMENT(offer_d_bus_tube);
1860
 
  IMPLEMENT(offer_stream_unix_tube);
1861
 
  */
1862
 
  IMPLEMENT(accept_tube);
1863
 
  IMPLEMENT(close_tube);
1864
 
  IMPLEMENT(get_d_bus_server_address);
 
2066
  IMPLEMENT(accept_d_bus_tube);
 
2067
  IMPLEMENT(get_d_bus_tube_address);
1865
2068
  IMPLEMENT(get_d_bus_names);
1866
 
  /*
1867
 
  IMPLEMENT(get_stream_unix_socket_address);
1868
 
  */
 
2069
  IMPLEMENT(offer_stream_tube);
 
2070
  IMPLEMENT(accept_stream_tube);
 
2071
  IMPLEMENT(get_stream_tube_socket_address);
 
2072
  IMPLEMENT(get_available_stream_tube_types);
1869
2073
#undef IMPLEMENT
1870
2074
}
1871
2075