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

« back to all changes in this revision

Viewing changes to src/tube-dbus.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:
1
1
/*
2
2
 * tube-dbus.c - Source for SalutTubeDBus
3
 
 * Copyright (C) 2007 Ltd.
 
3
 * Copyright (C) 2007-2008 Collabora Ltd.
4
4
 *
5
5
 * This library is free software; you can redistribute it and/or
6
6
 * modify it under the terms of the GNU Lesser General Public
22
22
#include <stdlib.h>
23
23
#include <string.h>
24
24
#include <time.h>
 
25
#include <errno.h>
25
26
 
26
27
#include <glib.h>
 
28
#include <glib/gstdio.h>
27
29
 
28
30
#include <dbus/dbus-glib.h>
29
31
#include <dbus/dbus-glib-lowlevel.h>
30
32
#include <telepathy-glib/util.h>
31
33
 
32
34
#include <gibber/gibber-bytestream-ibb.h>
 
35
#include <gibber/gibber-bytestream-muc.h>
33
36
#include <gibber/gibber-muc-connection.h>
34
37
 
35
38
#define DEBUG_FLAG DEBUG_TUBES
36
39
#include "debug.h"
37
 
#include "extensions/extensions.h"
38
40
#include "salut-connection.h"
39
 
#include "namespaces.h"
40
41
#include "tube-iface.h"
 
42
#include "sha1/sha1-util.h"
41
43
 
42
 
/*
43
 
#include "bytestream-factory.h"
44
 
*/
 
44
/* When we receive D-Bus messages to be delivered to the application and the
 
45
 * application is not yet connected to the D-Bus tube, theses D-Bus messages
 
46
 * are queued and delivered when the application connects to the D-Bus tube.
 
47
 *
 
48
 * If the application never connects, there is a risk that the contact sends
 
49
 * too many messages and eat all the memory. To avoid this, there is an
 
50
 * arbitrary limit on the queue size set to 4MB. */
 
51
#define MAX_QUEUE_SIZE (4096*1024)
45
52
 
46
53
static void
47
54
tube_iface_init (gpointer g_iface, gpointer iface_data);
90
97
  TpHandle self_handle;
91
98
  GibberMucConnection *muc_connection;
92
99
  guint id;
93
 
  GibberBytestreamIBB *bytestream;
 
100
  GibberBytestreamIface *bytestream;
94
101
  gchar *stream_id;
95
102
  TpHandle initiator;
96
103
  gchar *service;
100
107
  gchar *dbus_local_name;
101
108
  /* the address that we are listening for D-Bus connections on */
102
109
  gchar *dbus_srv_addr;
 
110
  /* the path of the UNIX socket used by the D-Bus server */
 
111
  gchar *socket_path;
103
112
  /* the server that's listening on dbus_srv_addr */
104
113
  DBusServer *dbus_srv;
105
114
  /* the connection to dbus_srv from a local client, or NULL */
106
115
  DBusConnection *dbus_conn;
107
 
  /* mapping of contact handle -> D-Bus name */
 
116
  /* the queue of D-Bus messages to be delivered to a local client when it
 
117
   * will connect */
 
118
  GSList *dbus_msg_queue;
 
119
  /* current size of the queue in bytes. The maximum is MAX_QUEUE_SIZE */
 
120
  unsigned long dbus_msg_queue_size;
 
121
  /* mapping of contact handle -> D-Bus name (NULL for 1-1 D-Bus tubes) */
108
122
  GHashTable *dbus_names;
109
123
 
 
124
  /* Message reassembly buffer (CONTACT tubes only) */
 
125
  GString *reassembly_buffer;
 
126
  /* Number of bytes that will be in the next message, 0 if unknown */
 
127
  guint32 reassembly_bytes_needed;
 
128
 
110
129
  gboolean dispose_has_run;
111
130
};
112
131
 
113
132
#define SALUT_TUBE_DBUS_GET_PRIVATE(obj) \
114
 
    ((SalutTubeDBusPrivate *) obj->priv)
 
133
    ((SalutTubeDBusPrivate *) ((SalutTubeDBus *)obj)->priv)
115
134
 
116
 
static void data_received_cb (GibberBytestreamIBB *ibb, const gchar *from,
117
 
    GString *data, gpointer user_data);
 
135
static void data_received_cb (GibberBytestreamIface *bytestream,
 
136
    const gchar *from, GString *data, gpointer user_data);
118
137
 
119
138
/*
120
139
 * Characters used are permissible both in filenames and in D-Bus names. (See
135
154
    buf[i] = chars[g_random_int_range (0, 64)];
136
155
}
137
156
 
 
157
static gchar *
 
158
generate_dbus_unique_name (const gchar *nick)
 
159
{
 
160
  gchar *encoded, *result;
 
161
  size_t len;
 
162
  guint i;
 
163
 
 
164
  len = strlen (nick);
 
165
 
 
166
  if (len <= 186)
 
167
    {
 
168
      encoded = g_base64_encode ((const guchar *) nick, strlen (nick));
 
169
    }
 
170
  else
 
171
    {
 
172
      guchar sha1[20];
 
173
      GString *tmp;
 
174
 
 
175
      sha1_bin (nick, len, sha1);
 
176
      tmp = g_string_sized_new (169 + 20);
 
177
 
 
178
      g_string_append_len (tmp, nick, 169);
 
179
      g_string_append_len (tmp, (const gchar *) sha1, 20);
 
180
 
 
181
      encoded = g_base64_encode ((const guchar *) tmp->str, tmp->len);
 
182
 
 
183
      g_string_free (tmp, TRUE);
 
184
    }
 
185
 
 
186
  for (i = 0; encoded[i] != '\0'; i++)
 
187
    {
 
188
      switch (encoded[i])
 
189
        {
 
190
          case '+':
 
191
            encoded[i] = '_';
 
192
            break;
 
193
          case '/':
 
194
            encoded[i] = '-';
 
195
            break;
 
196
          case '=':
 
197
            encoded[i] = 'A';
 
198
            break;
 
199
        }
 
200
    }
 
201
 
 
202
  result = g_strdup_printf (":2.%s", encoded);
 
203
 
 
204
  g_free (encoded);
 
205
  return result;
 
206
}
 
207
 
138
208
struct _find_contact_data
139
209
{
140
210
  const gchar *contact;
150
220
  SalutTubeDBusPrivate *priv = SALUT_TUBE_DBUS_GET_PRIVATE (tube);
151
221
  gchar *marshalled = NULL;
152
222
  gint len;
 
223
  const gchar *destination;
 
224
  dbus_uint32_t serial;
153
225
 
154
226
  if (dbus_message_get_type (msg) == DBUS_MESSAGE_TYPE_SIGNAL &&
155
227
      !tp_strdiff (dbus_message_get_interface (msg),
164
236
      goto out;
165
237
    }
166
238
 
167
 
  dbus_message_set_sender (msg, priv->dbus_local_name);
 
239
  if (priv->dbus_local_name != NULL)
 
240
    {
 
241
      dbus_message_set_sender (msg, priv->dbus_local_name);
 
242
    }
168
243
 
169
244
  if (!dbus_message_marshal (msg, &marshalled, &len))
170
245
    goto out;
171
246
 
172
 
  gibber_bytestream_ibb_send (priv->bytestream, len, marshalled);
 
247
  gibber_bytestream_iface_send (priv->bytestream, len, marshalled);
 
248
 
 
249
  if (GIBBER_IS_BYTESTREAM_MUC (priv->bytestream))
 
250
    {
 
251
      /* In a Salut MUC we never receive messages we sent, so we need to
 
252
       * artificially receive our own messages. */
 
253
      destination = dbus_message_get_destination (msg);
 
254
      if (destination == NULL || !tp_strdiff (priv->dbus_local_name,
 
255
            destination))
 
256
        {
 
257
          dbus_connection_send (priv->dbus_conn, msg, &serial);
 
258
        }
 
259
    }
173
260
 
174
261
out:
175
262
  if (marshalled != NULL)
185
272
{
186
273
  SalutTubeDBus *tube = SALUT_TUBE_DBUS (data);
187
274
  SalutTubeDBusPrivate *priv = SALUT_TUBE_DBUS_GET_PRIVATE (tube);
 
275
  guint32 serial;
 
276
  GSList *i;
188
277
 
189
278
  if (priv->dbus_conn != NULL)
190
279
    /* we already have a connection; drop this new one */
197
286
  dbus_connection_setup_with_g_main (conn, NULL);
198
287
  dbus_connection_add_filter (conn, filter_cb, tube, NULL);
199
288
  priv->dbus_conn = conn;
 
289
 
 
290
  /* We may have received messages to deliver before the local connection is
 
291
   * established. Theses messages are kept in the dbus_msg_queue list and are
 
292
   * delivered as soon as we get the connection. */
 
293
  DEBUG ("%u messages in the queue (%lu bytes)",
 
294
         g_slist_length (priv->dbus_msg_queue), priv->dbus_msg_queue_size);
 
295
  priv->dbus_msg_queue = g_slist_reverse (priv->dbus_msg_queue);
 
296
  for (i = priv->dbus_msg_queue; i != NULL; i = g_slist_delete_link (i, i))
 
297
    {
 
298
      DBusMessage *msg = i->data;
 
299
      DEBUG ("delivering queued message from '%s' to '%s' on the "
 
300
             "new connection",
 
301
             dbus_message_get_sender (msg),
 
302
             dbus_message_get_destination (msg));
 
303
      dbus_connection_send (priv->dbus_conn, msg, &serial);
 
304
      dbus_message_unref (msg);
 
305
    }
 
306
  priv->dbus_msg_queue = NULL;
 
307
  priv->dbus_msg_queue_size = 0;
200
308
}
201
309
 
202
310
static void
203
311
tube_dbus_open (SalutTubeDBus *self)
204
312
{
 
313
#define SERVER_LISTEN_MAX_TRIES 5
205
314
  SalutTubeDBusPrivate *priv = SALUT_TUBE_DBUS_GET_PRIVATE (self);
206
 
  DBusError error = {0,};
207
 
  gchar suffix[8];
 
315
  guint i;
208
316
 
209
317
  g_signal_connect (priv->bytestream, "data-received",
210
318
      G_CALLBACK (data_received_cb), self);
211
319
 
212
 
  generate_ascii_string (8, suffix);
213
 
  priv->dbus_srv_addr = g_strdup_printf (
214
 
      "unix:path=/tmp/dbus-salut-%.8s", suffix);
 
320
  for (i = 0; i < SERVER_LISTEN_MAX_TRIES; i++)
 
321
    {
 
322
      gchar suffix[8];
 
323
      DBusError error;
 
324
 
 
325
      g_free (priv->dbus_srv_addr);
 
326
      g_free (priv->socket_path);
 
327
 
 
328
      generate_ascii_string (8, suffix);
 
329
      priv->socket_path = g_strdup_printf ("%s/dbus-salut-%.8s",
 
330
          g_get_tmp_dir (), suffix);
 
331
      priv->dbus_srv_addr = g_strdup_printf ("unix:path=%s",
 
332
          priv->socket_path);
 
333
 
 
334
      dbus_error_init (&error);
 
335
      priv->dbus_srv = dbus_server_listen (priv->dbus_srv_addr, &error);
 
336
 
 
337
      if (priv->dbus_srv_addr != NULL)
 
338
        break;
 
339
 
 
340
      DEBUG ("dbus_server_listen failed (try %u): %s: %s", i, error.name,
 
341
          error.message);
 
342
      dbus_error_free (&error);
 
343
    }
 
344
 
 
345
  if (priv->dbus_srv_addr == NULL)
 
346
    {
 
347
      DEBUG ("all attempts failed. Close the tube");
 
348
      salut_tube_iface_accept (SALUT_TUBE_IFACE (self), NULL);
 
349
      return;
 
350
    }
 
351
 
215
352
  DEBUG ("listening on %s", priv->dbus_srv_addr);
216
 
  priv->dbus_srv = dbus_server_listen (priv->dbus_srv_addr, &error);
217
 
 
218
 
  /* XXX: if dbus_server_listen fails, we should retry with different
219
 
   * addresses, then close the tube if we give up
220
 
   */
221
 
  g_assert (priv->dbus_srv);
222
353
 
223
354
  dbus_server_set_new_connection_function (priv->dbus_srv, new_connection_cb,
224
355
      self, NULL);
230
361
{
231
362
  SalutTubeDBusPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
232
363
      SALUT_TYPE_TUBE_DBUS, SalutTubeDBusPrivate);
233
 
  gchar suffix[8];
234
364
 
235
365
  self->priv = priv;
236
 
 
237
 
  priv->bytestream = NULL;
238
 
  priv->muc_connection = NULL;
239
 
  priv->dispose_has_run = FALSE;
240
 
 
241
 
  /* XXX: check this doesn't clash with other bus names */
242
 
  /* this has to contain at least two dot-separated components */
243
 
 
244
 
  generate_ascii_string (8, suffix);
245
 
  priv->dbus_local_name = g_strdup_printf (":1.%.8s", suffix);
246
 
  priv->dbus_names = g_hash_table_new_full (g_direct_hash, g_direct_equal,
247
 
      NULL, g_free);
248
 
 
249
 
  DEBUG ("local name: %s", priv->dbus_local_name);
250
366
}
251
367
 
252
368
static void
260
376
  tp_handle_unref (contact_repo, handle);
261
377
}
262
378
 
263
 
static SalutTubeState
 
379
static TpTubeState
264
380
get_tube_state (SalutTubeDBus *self)
265
381
{
266
382
  SalutTubeDBusPrivate *priv = SALUT_TUBE_DBUS_GET_PRIVATE (self);
267
 
  GibberBytestreamIBBState bytestream_state;
 
383
  GibberBytestreamState bytestream_state;
268
384
 
269
385
  if (priv->bytestream == NULL)
270
386
    /* bytestream not yet created as we're waiting for the SI reply */
271
 
    return SALUT_TUBE_STATE_REMOTE_PENDING;
 
387
    return TP_TUBE_STATE_REMOTE_PENDING;
272
388
 
273
389
  g_object_get (priv->bytestream, "state", &bytestream_state, NULL);
274
390
 
275
 
  if (bytestream_state == GIBBER_BYTESTREAM_IBB_STATE_OPEN)
276
 
    return SALUT_TUBE_STATE_OPEN;
277
 
 
278
 
  else if (bytestream_state == GIBBER_BYTESTREAM_IBB_STATE_LOCAL_PENDING ||
279
 
      bytestream_state == GIBBER_BYTESTREAM_IBB_STATE_ACCEPTED)
280
 
    return SALUT_TUBE_STATE_LOCAL_PENDING;
281
 
 
282
 
  else if (bytestream_state == GIBBER_BYTESTREAM_IBB_STATE_INITIATING)
283
 
    return SALUT_TUBE_STATE_REMOTE_PENDING;
284
 
 
285
 
  else
286
 
    g_assert_not_reached ();
287
 
  return SALUT_TUBE_STATE_REMOTE_PENDING;
 
391
  switch (bytestream_state)
 
392
    {
 
393
      case GIBBER_BYTESTREAM_STATE_OPEN:
 
394
        return TP_TUBE_STATE_OPEN;
 
395
        break;
 
396
      case GIBBER_BYTESTREAM_STATE_LOCAL_PENDING:
 
397
      case GIBBER_BYTESTREAM_STATE_ACCEPTED:
 
398
        return TP_TUBE_STATE_LOCAL_PENDING;
 
399
        break;
 
400
      case GIBBER_BYTESTREAM_STATE_INITIATING:
 
401
        return TP_TUBE_STATE_REMOTE_PENDING;
 
402
        break;
 
403
      default:
 
404
        g_assert_not_reached ();
 
405
    }
288
406
}
289
407
 
290
408
static void
291
 
bytestream_state_changed_cb (GibberBytestreamIBB *bytestream,
292
 
                             GibberBytestreamIBBState state,
 
409
bytestream_state_changed_cb (GibberBytestreamIface *bytestream,
 
410
                             GibberBytestreamState state,
293
411
                             gpointer user_data)
294
412
{
295
413
  SalutTubeDBus *self = SALUT_TUBE_DBUS (user_data);
296
414
  SalutTubeDBusPrivate *priv = SALUT_TUBE_DBUS_GET_PRIVATE (self);
297
415
 
298
 
  if (state == GIBBER_BYTESTREAM_IBB_STATE_CLOSED)
 
416
  if (state == GIBBER_BYTESTREAM_STATE_CLOSED)
299
417
    {
300
418
      if (priv->bytestream != NULL)
301
419
        {
305
423
 
306
424
      g_signal_emit (G_OBJECT (self), signals[CLOSED], 0);
307
425
    }
308
 
  else if (state == GIBBER_BYTESTREAM_IBB_STATE_OPEN)
 
426
  else if (state == GIBBER_BYTESTREAM_STATE_OPEN)
309
427
    {
310
428
      tube_dbus_open (self);
311
429
      g_signal_emit (G_OBJECT (self), signals[OPENED], 0);
325
443
 
326
444
  if (priv->bytestream)
327
445
    {
328
 
      gibber_bytestream_ibb_close (priv->bytestream);
 
446
      gibber_bytestream_iface_close (priv->bytestream, NULL);
329
447
    }
330
448
 
331
449
  if (priv->dbus_conn)
337
455
  if (priv->dbus_srv)
338
456
    dbus_server_unref (priv->dbus_srv);
339
457
 
340
 
  if (priv->dbus_srv_addr)
341
 
    g_free (priv->dbus_srv_addr);
342
 
 
343
 
  if (priv->dbus_local_name)
344
 
    g_free (priv->dbus_local_name);
 
458
  if (priv->socket_path != NULL)
 
459
    {
 
460
      if (g_unlink (priv->socket_path) != 0)
 
461
        {
 
462
          DEBUG ("unlink of %s failed: %s", priv->socket_path,
 
463
              g_strerror (errno));
 
464
        }
 
465
    }
 
466
 
 
467
  if (priv->dbus_msg_queue != NULL)
 
468
    {
 
469
      GSList *i;
 
470
      for (i = priv->dbus_msg_queue; i != NULL; i = g_slist_delete_link (i, i))
 
471
        {
 
472
          DBusMessage *msg = i->data;
 
473
          dbus_message_unref (msg);
 
474
        }
 
475
      priv->dbus_msg_queue = NULL;
 
476
      priv->dbus_msg_queue_size = 0;
 
477
    }
 
478
 
 
479
  g_free (priv->dbus_srv_addr);
 
480
  priv->dbus_srv_addr = NULL;
 
481
  g_free (priv->socket_path);
 
482
  priv->socket_path = NULL;
 
483
  g_free (priv->dbus_local_name);
 
484
  priv->dbus_local_name = NULL;
345
485
 
346
486
  if (priv->dbus_names)
347
487
    {
358
498
      priv->muc_connection = NULL;
359
499
    }
360
500
 
 
501
  if (priv->reassembly_buffer)
 
502
    g_string_free (priv->reassembly_buffer, TRUE);
 
503
 
361
504
  tp_handle_unref (contact_repo, priv->initiator);
362
505
 
363
506
  priv->dispose_has_run = TRUE;
415
558
        g_value_set_string (value, priv->stream_id);
416
559
        break;
417
560
      case PROP_TYPE:
418
 
        g_value_set_uint (value, SALUT_TUBE_TYPE_DBUS);
 
561
        g_value_set_uint (value, TP_TUBE_TYPE_DBUS);
419
562
        break;
420
563
      case PROP_INITIATOR:
421
564
        g_value_set_uint (value, priv->initiator);
477
620
      case PROP_BYTESTREAM:
478
621
        if (priv->bytestream == NULL)
479
622
          {
480
 
            GibberBytestreamIBBState state;
 
623
            GibberBytestreamState state;
481
624
 
482
625
            priv->bytestream = g_value_get_object (value);
483
626
            g_object_ref (priv->bytestream);
484
627
 
485
628
            g_object_get (priv->bytestream, "state", &state, NULL);
486
 
            if (state == GIBBER_BYTESTREAM_IBB_STATE_OPEN)
 
629
            if (state == GIBBER_BYTESTREAM_STATE_OPEN)
487
630
              {
488
631
                tube_dbus_open (self);
489
632
              }
492
635
                G_CALLBACK (bytestream_state_changed_cb), self);
493
636
          }
494
637
        break;
495
 
      case PROP_STREAM_ID:
496
 
        g_free (priv->stream_id);
497
 
        priv->stream_id = g_value_dup_string (value);
498
 
        break;
499
638
      case PROP_INITIATOR:
500
639
        priv->initiator = g_value_get_uint (value);
501
640
        break;
543
682
  if (priv->handle_type == TP_HANDLE_TYPE_ROOM)
544
683
    {
545
684
      /*
546
 
       * We have to create an IBB bytestream that will be
 
685
       * We have to create an MUC bytestream that will be
547
686
       * used by this MUC tube to communicate.
548
687
       *
549
688
       * We don't create the bytestream of private D-Bus tube yet.
550
689
       * It will be when we'll receive the answer of the SI request
551
690
       */
552
 
      GibberBytestreamIBB *bytestream;
553
 
      GibberBytestreamIBBState state;
 
691
      GibberBytestreamMuc *bytestream;
 
692
      GibberBytestreamState state;
554
693
      const gchar *peer_id;
555
694
 
556
695
      g_assert (priv->muc_connection != NULL);
557
 
      g_assert (priv->stream_id != NULL);
 
696
 
 
697
      priv->dbus_names = g_hash_table_new_full (g_direct_hash, g_direct_equal,
 
698
          NULL, g_free);
 
699
 
 
700
      priv->dbus_local_name = generate_dbus_unique_name (priv->conn->name);
 
701
 
 
702
      DEBUG ("local name: %s", priv->dbus_local_name);
558
703
 
559
704
      peer_id = tp_handle_inspect (handles_repo, priv->handle);
560
705
      if (priv->initiator == priv->self_handle)
561
706
        {
562
707
          /* We create this tube, bytestream is open */
563
 
          state = GIBBER_BYTESTREAM_IBB_STATE_OPEN;
 
708
          state = GIBBER_BYTESTREAM_STATE_OPEN;
564
709
        }
565
710
      else
566
711
        {
567
712
          /* We don't create this tube, bytestream is local pending */
568
 
          state = GIBBER_BYTESTREAM_IBB_STATE_LOCAL_PENDING;
 
713
          state = GIBBER_BYTESTREAM_STATE_LOCAL_PENDING;
569
714
        }
570
715
 
571
 
      bytestream = g_object_new (GIBBER_TYPE_BYTESTREAM_IBB,
 
716
      bytestream = g_object_new (GIBBER_TYPE_BYTESTREAM_MUC,
572
717
            "muc-connection", priv->muc_connection,
573
 
            "stream-id", priv->stream_id,
574
718
            "state", state,
575
719
            "self-id", priv->conn->name,
576
720
            "peer-id", peer_id,
577
 
            "stream-init-id", NULL,
578
721
            NULL);
579
722
 
 
723
      g_object_get (bytestream, "stream-id", &priv->stream_id, NULL);
 
724
 
580
725
      g_object_set (self, "bytestream", bytestream, NULL);
 
726
      g_object_unref (bytestream);
581
727
    }
582
728
  else
583
729
    {
584
730
      /* Private tube */
585
731
      g_assert (priv->muc_connection == NULL);
 
732
 
 
733
      /* The D-Bus names mapping is used in muc tubes only */
 
734
      priv->dbus_local_name = NULL;
 
735
      priv->dbus_names = NULL;
 
736
 
 
737
      /* For contact tubes we need to be able to reassemble messages. */
 
738
      priv->reassembly_buffer = g_string_new ("");
 
739
      priv->reassembly_bytes_needed = 0;
586
740
    }
587
741
 
588
742
  return obj;
604
758
  object_class->dispose = salut_tube_dbus_dispose;
605
759
  object_class->finalize = salut_tube_dbus_finalize;
606
760
 
607
 
  param_spec = g_param_spec_object (
608
 
      "connection",
609
 
      "SalutConnection object",
610
 
      "Salut connection object that owns this D-Bus tube object.",
611
 
      SALUT_TYPE_CONNECTION,
612
 
      G_PARAM_CONSTRUCT_ONLY |
613
 
      G_PARAM_READWRITE |
614
 
      G_PARAM_STATIC_NAME |
615
 
      G_PARAM_STATIC_NICK |
616
 
      G_PARAM_STATIC_BLURB);
617
 
  g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
618
 
 
619
 
 param_spec = g_param_spec_uint (
620
 
      "handle",
621
 
      "Handle",
622
 
      "The TpHandle associated with the tubes channel that"
623
 
      "owns this D-Bus tube object.",
624
 
      0, G_MAXUINT32, 0,
625
 
      G_PARAM_CONSTRUCT_ONLY |
626
 
      G_PARAM_READWRITE |
627
 
      G_PARAM_STATIC_NAME |
628
 
      G_PARAM_STATIC_NICK |
629
 
      G_PARAM_STATIC_BLURB);
630
 
  g_object_class_install_property (object_class, PROP_HANDLE, param_spec);
631
 
 
632
 
  param_spec = g_param_spec_uint (
633
 
      "handle-type",
634
 
      "Handle type",
635
 
      "The TpHandleType of the handle associated with the tubes channel that"
636
 
      "owns this D-Bus tube object.",
637
 
      0, G_MAXUINT32, 0,
638
 
      G_PARAM_CONSTRUCT_ONLY |
639
 
      G_PARAM_READWRITE |
640
 
      G_PARAM_STATIC_NAME |
641
 
      G_PARAM_STATIC_NICK |
642
 
      G_PARAM_STATIC_BLURB);
643
 
  g_object_class_install_property (object_class, PROP_HANDLE_TYPE,
644
 
      param_spec);
645
 
 
646
 
  param_spec = g_param_spec_uint (
647
 
      "self-handle",
648
 
      "Self handle",
649
 
      "The handle to use for ourself. This can be different from the "
650
 
      "connection's self handle if our handle is a room handle.",
651
 
      0, G_MAXUINT, 0,
652
 
      G_PARAM_CONSTRUCT_ONLY |
653
 
      G_PARAM_READWRITE |
654
 
      G_PARAM_STATIC_NAME |
655
 
      G_PARAM_STATIC_NICK |
656
 
      G_PARAM_STATIC_BLURB);
657
 
  g_object_class_install_property (object_class, PROP_SELF_HANDLE, param_spec);
 
761
  g_object_class_override_property (object_class, PROP_CONNECTION,
 
762
    "connection");
 
763
  g_object_class_override_property (object_class, PROP_HANDLE,
 
764
    "handle");
 
765
  g_object_class_override_property (object_class, PROP_HANDLE_TYPE,
 
766
    "handle-type");
 
767
  g_object_class_override_property (object_class, PROP_SELF_HANDLE,
 
768
    "self-handle");
 
769
  g_object_class_override_property (object_class, PROP_ID,
 
770
    "id");
 
771
  g_object_class_override_property (object_class, PROP_TYPE,
 
772
    "type");
 
773
  g_object_class_override_property (object_class, PROP_INITIATOR,
 
774
    "initiator");
 
775
  g_object_class_override_property (object_class, PROP_SERVICE,
 
776
    "service");
 
777
  g_object_class_override_property (object_class, PROP_PARAMETERS,
 
778
    "parameters");
 
779
  g_object_class_override_property (object_class, PROP_STATE,
 
780
    "state");
658
781
 
659
782
  param_spec = g_param_spec_object (
660
783
      "muc-connection",
670
793
  g_object_class_install_property (object_class, PROP_MUC_CONNECTION,
671
794
      param_spec);
672
795
 
673
 
  param_spec = g_param_spec_uint (
674
 
      "id",
675
 
      "id",
676
 
      "The unique identifier of this tube",
677
 
      0, G_MAXUINT32, 0,
678
 
      G_PARAM_CONSTRUCT_ONLY |
679
 
      G_PARAM_READWRITE |
680
 
      G_PARAM_STATIC_NAME |
681
 
      G_PARAM_STATIC_NICK |
682
 
      G_PARAM_STATIC_BLURB);
683
 
  g_object_class_install_property (object_class, PROP_ID, param_spec);
684
 
 
685
796
  param_spec = g_param_spec_object (
686
797
      "bytestream",
687
 
      "SalutBytestreamIBB object",
688
 
      "Salut bytestream IBB object used for streaming data for this D-Bus"
689
 
      "tube object.",
690
 
      GIBBER_TYPE_BYTESTREAM_IBB,
 
798
      "Object implementing the GibberBytestreamIface interface",
 
799
      "Bytestream object used for streaming data for this D-Bus",
 
800
      G_TYPE_OBJECT,
691
801
      G_PARAM_READWRITE |
692
802
      G_PARAM_STATIC_NAME |
693
803
      G_PARAM_STATIC_NICK |
699
809
      "stream id",
700
810
      "The identifier of this tube's bytestream",
701
811
      "",
702
 
      G_PARAM_CONSTRUCT_ONLY |
703
 
      G_PARAM_READWRITE |
 
812
      G_PARAM_READABLE |
704
813
      G_PARAM_STATIC_NAME |
705
814
      G_PARAM_STATIC_NICK |
706
815
      G_PARAM_STATIC_BLURB);
707
816
  g_object_class_install_property (object_class, PROP_STREAM_ID, param_spec);
708
817
 
709
 
  param_spec = g_param_spec_uint (
710
 
      "type",
711
 
      "Tube type",
712
 
      "The TpTubeType this D-Bus tube object.",
713
 
      0, G_MAXUINT32, SALUT_TUBE_TYPE_DBUS,
714
 
      G_PARAM_READABLE |
715
 
      G_PARAM_STATIC_NAME |
716
 
      G_PARAM_STATIC_NICK |
717
 
      G_PARAM_STATIC_BLURB);
718
 
  g_object_class_install_property (object_class, PROP_TYPE, param_spec);
719
 
 
720
 
  param_spec = g_param_spec_uint (
721
 
      "initiator",
722
 
      "Initiator handle",
723
 
      "The TpHandle of the initiator of this D-Bus tube object.",
724
 
      0, G_MAXUINT32, 0,
725
 
      G_PARAM_CONSTRUCT_ONLY |
726
 
      G_PARAM_READWRITE |
727
 
      G_PARAM_STATIC_NAME |
728
 
      G_PARAM_STATIC_NICK |
729
 
      G_PARAM_STATIC_BLURB);
730
 
  g_object_class_install_property (object_class, PROP_INITIATOR, param_spec);
731
 
 
732
 
  param_spec = g_param_spec_string (
733
 
      "service",
734
 
      "service name",
735
 
      "the service associated with this D-BUS tube object.",
736
 
      "",
737
 
      G_PARAM_CONSTRUCT_ONLY |
738
 
      G_PARAM_READWRITE |
739
 
      G_PARAM_STATIC_NAME |
740
 
      G_PARAM_STATIC_NICK |
741
 
      G_PARAM_STATIC_BLURB);
742
 
  g_object_class_install_property (object_class, PROP_SERVICE, param_spec);
743
 
 
744
 
  param_spec = g_param_spec_boxed (
745
 
      "parameters",
746
 
      "parameters GHashTable",
747
 
      "GHashTable containing parameters of this DBUS tube object.",
748
 
      G_TYPE_HASH_TABLE,
749
 
      G_PARAM_CONSTRUCT_ONLY |
750
 
      G_PARAM_READWRITE |
751
 
      G_PARAM_STATIC_NAME |
752
 
      G_PARAM_STATIC_NICK |
753
 
      G_PARAM_STATIC_BLURB);
754
 
  g_object_class_install_property (object_class, PROP_PARAMETERS, param_spec);
755
 
 
756
 
  param_spec = g_param_spec_uint (
757
 
      "state",
758
 
      "Tube state",
759
 
      "The SalutTubeState of this DBUS tube object",
760
 
      0, G_MAXUINT32, SALUT_TUBE_STATE_REMOTE_PENDING,
761
 
      G_PARAM_READABLE |
762
 
      G_PARAM_STATIC_NAME |
763
 
      G_PARAM_STATIC_NICK |
764
 
      G_PARAM_STATIC_BLURB);
765
 
  g_object_class_install_property (object_class, PROP_STATE, param_spec);
766
 
 
767
818
  param_spec = g_param_spec_string (
768
819
      "dbus-address",
769
820
      "D-Bus address",
818
869
}
819
870
 
820
871
static void
821
 
data_received_cb (GibberBytestreamIBB *ibb,
 
872
message_received (SalutTubeDBus *tube,
 
873
                  TpHandle sender,
 
874
                  const char *data,
 
875
                  size_t len)
 
876
{
 
877
  SalutTubeDBusPrivate *priv = SALUT_TUBE_DBUS_GET_PRIVATE (tube);
 
878
  DBusMessage *msg;
 
879
  DBusError error = {0,};
 
880
  guint32 serial;
 
881
 
 
882
  msg = dbus_message_demarshal (data, len, &error);
 
883
 
 
884
  if (msg == NULL)
 
885
    {
 
886
      /* message was corrupted */
 
887
      DEBUG ("received corrupted message from %d: %s: %s", sender,
 
888
          error.name, error.message);
 
889
      dbus_error_free (&error);
 
890
      return;
 
891
    }
 
892
 
 
893
  if (priv->handle_type == TP_HANDLE_TYPE_ROOM)
 
894
    {
 
895
      const gchar *destination;
 
896
      const gchar *sender_name;
 
897
 
 
898
      destination = dbus_message_get_destination (msg);
 
899
      /* If destination is NULL this msg is broadcasted (signals) so we don't
 
900
       * have to check it */
 
901
      if (destination != NULL && tp_strdiff (priv->dbus_local_name,
 
902
            destination))
 
903
        {
 
904
          /* This message is not intended to this tube.
 
905
           * Discard it. */
 
906
          DEBUG ("message not intended to this tube (destination = %s)",
 
907
              destination);
 
908
          goto unref;
 
909
        }
 
910
 
 
911
      sender_name = g_hash_table_lookup (priv->dbus_names,
 
912
          GUINT_TO_POINTER (sender));
 
913
 
 
914
      if (tp_strdiff (sender_name, dbus_message_get_sender (msg)))
 
915
        {
 
916
          DEBUG ("invalid sender %s (expected %s for sender handle %d)",
 
917
                 dbus_message_get_sender (msg), sender_name, sender);
 
918
          goto unref;
 
919
        }
 
920
    }
 
921
 
 
922
  if (!priv->dbus_conn)
 
923
    {
 
924
      DEBUG ("no D-Bus connection: queuing the message");
 
925
 
 
926
      /* If the application never connects to the private dbus connection, we
 
927
       * don't want to eat all the memory. Only queue MAX_QUEUE_SIZE bytes. If
 
928
       * there are more messages, drop them. */
 
929
      if (priv->dbus_msg_queue_size + len > MAX_QUEUE_SIZE)
 
930
        {
 
931
          DEBUG ("D-Bus message queue size limit reached (%u bytes). "
 
932
                 "Ignore this message.",
 
933
                 MAX_QUEUE_SIZE);
 
934
          goto unref;
 
935
        }
 
936
 
 
937
      priv->dbus_msg_queue = g_slist_prepend (priv->dbus_msg_queue, msg);
 
938
      priv->dbus_msg_queue_size += len;
 
939
 
 
940
      /* returns without unref the message */
 
941
      return;
 
942
    }
 
943
 
 
944
  DEBUG ("delivering message from '%s' to '%s'",
 
945
         dbus_message_get_sender (msg),
 
946
         dbus_message_get_destination (msg));
 
947
 
 
948
  /* XXX: what do do if this returns FALSE? */
 
949
  dbus_connection_send (priv->dbus_conn, msg, &serial);
 
950
 
 
951
unref:
 
952
  dbus_message_unref (msg);
 
953
}
 
954
 
 
955
static guint32
 
956
collect_le32 (char *str)
 
957
{
 
958
  unsigned char *bytes = (unsigned char *) str;
 
959
 
 
960
  return bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
 
961
}
 
962
 
 
963
static guint32
 
964
collect_be32 (char *str)
 
965
{
 
966
  unsigned char *bytes = (unsigned char *) str;
 
967
 
 
968
  return (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 24) | bytes[3];
 
969
}
 
970
 
 
971
static void
 
972
data_received_cb (GibberBytestreamIface *stream,
822
973
                  const gchar *from,
823
974
                  GString *data,
824
975
                  gpointer user_data)
828
979
  TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
829
980
      (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
830
981
  TpHandle sender;
831
 
  DBusMessage *msg;
832
 
  DBusError error = {0,};
833
 
  guint32 serial;
834
 
  const gchar *sender_name;
835
 
  const gchar *destination;
836
 
 
837
 
  if (!priv->dbus_conn)
838
 
    {
839
 
      DEBUG ("no D-Bus connection");
840
 
      return;
841
 
    }
842
 
 
843
 
  /* XXX: This naïvely assumes that the underlying transport always gives
844
 
   * us complete messages. This is true for IBB, at least.
845
 
   */
846
 
 
847
 
  msg = dbus_message_demarshal (data->str, data->len, &error);
848
 
  if (!msg)
849
 
    {
850
 
      /* message was corrupted */
851
 
      DEBUG ("received corrupted message from %s", from);
852
 
      return;
853
 
    }
854
 
 
855
 
  destination = dbus_message_get_destination (msg);
856
 
  /* If destination is NULL this msg is broadcasted (signals) so we don't have
857
 
   * to check it */
858
 
  if (destination != NULL && tp_strdiff (priv->dbus_local_name, destination))
859
 
    {
860
 
      /* This message is not intended to this tube.
861
 
       * Discard it. */
862
 
      DEBUG ("message not intended to this tube (destination = %s)",
863
 
          destination);
864
 
      dbus_message_unref (msg);
865
 
      return;
866
 
    }
867
982
 
868
983
  sender = tp_handle_lookup (contact_repo, from, NULL, NULL);
869
984
  if (sender == 0)
870
985
    {
871
986
      DEBUG ("unkown sender: %s", from);
872
 
      dbus_message_unref (msg);
873
 
      return;
874
 
    }
875
 
 
876
 
  sender_name = g_hash_table_lookup (priv->dbus_names,
877
 
      GUINT_TO_POINTER (sender));
878
 
 
879
 
  if (tp_strdiff (sender_name, dbus_message_get_sender (msg)))
880
 
    {
881
 
      DEBUG ("invalid sender %s (expected %s for sender handle %d)",
882
 
             dbus_message_get_sender (msg), sender_name, sender);
883
 
      dbus_message_unref (msg);
884
 
      return;
885
 
    }
886
 
 
887
 
  /* XXX: what do do if this returns FALSE? */
888
 
  dbus_connection_send (priv->dbus_conn, msg, &serial);
889
 
 
890
 
  dbus_message_unref (msg);
 
987
      return;
 
988
    }
 
989
 
 
990
  if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
 
991
    {
 
992
      GString *buf = priv->reassembly_buffer;
 
993
 
 
994
      g_assert (buf != NULL);
 
995
 
 
996
      g_string_append_len (buf, data->str, data->len);
 
997
      DEBUG ("Received %" G_GSIZE_FORMAT " bytes, so we now have %"
 
998
          G_GSIZE_FORMAT " bytes in reassembly buffer", data->len, buf->len);
 
999
 
 
1000
      /* Each D-Bus message has a 16-byte fixed header, in which
 
1001
       *
 
1002
       * * byte 0 is 'l' (ell) or 'B' for endianness
 
1003
       * * bytes 4-7 are body length "n" in bytes in that endianness
 
1004
       * * bytes 12-15 are length "m" of param array in bytes in that
 
1005
       *   endianness
 
1006
       *
 
1007
       * followed by m + n + ((8 - (m % 8)) % 8) bytes of other content.
 
1008
       */
 
1009
 
 
1010
      while (buf->len >= 16)
 
1011
        {
 
1012
          guint32 body_length, params_length, m;
 
1013
 
 
1014
          /* see if we have a whole message and have already calculated
 
1015
           * how many bytes it needs */
 
1016
 
 
1017
          if (priv->reassembly_bytes_needed != 0)
 
1018
            {
 
1019
              if (buf->len >= priv->reassembly_bytes_needed)
 
1020
                {
 
1021
                  DEBUG ("Received complete D-Bus message of size %"
 
1022
                      G_GINT32_FORMAT, priv->reassembly_bytes_needed);
 
1023
                  message_received (tube, sender, buf->str,
 
1024
                      priv->reassembly_bytes_needed);
 
1025
                  g_string_erase (buf, 0, priv->reassembly_bytes_needed);
 
1026
                  priv->reassembly_bytes_needed = 0;
 
1027
                }
 
1028
              else
 
1029
                {
 
1030
                  /* we'll have to wait for more data */
 
1031
                  break;
 
1032
                }
 
1033
            }
 
1034
 
 
1035
          if (buf->len < 16)
 
1036
            break;
 
1037
 
 
1038
          /* work out how big the next message is going to be */
 
1039
 
 
1040
          if (buf->str[0] == DBUS_BIG_ENDIAN)
 
1041
            {
 
1042
              body_length = collect_be32 (buf->str + 4);
 
1043
              m = collect_be32 (buf->str + 12);
 
1044
            }
 
1045
          else if (buf->str[0] == DBUS_LITTLE_ENDIAN)
 
1046
            {
 
1047
              body_length = collect_le32 (buf->str + 4);
 
1048
              m = collect_le32 (buf->str + 12);
 
1049
            }
 
1050
          else
 
1051
            {
 
1052
              DEBUG ("D-Bus message has unknown endianness byte 0x%x, "
 
1053
                  "closing tube", (unsigned int) buf->str[0]);
 
1054
              salut_tube_iface_close (SALUT_TUBE_IFACE (tube));
 
1055
              return;
 
1056
            }
 
1057
 
 
1058
          /* pad to 8-byte boundary */
 
1059
          params_length = m + ((8 - (m % 8)) % 8);
 
1060
          g_assert (params_length % 8 == 0);
 
1061
          g_assert (params_length >= m);
 
1062
          g_assert (params_length < m + 8);
 
1063
 
 
1064
          priv->reassembly_bytes_needed = params_length + body_length + 16;
 
1065
 
 
1066
          /* n.b.: this looks as if it could be simplified to just the third
 
1067
           * test, but that would be wrong if the addition had overflowed, so
 
1068
           * don't do that. The first and second tests are sufficient to
 
1069
           * ensure no overflow on 32-bit platforms */
 
1070
          if (body_length > DBUS_MAXIMUM_MESSAGE_LENGTH ||
 
1071
              params_length > DBUS_MAXIMUM_ARRAY_LENGTH ||
 
1072
              priv->reassembly_bytes_needed > DBUS_MAXIMUM_MESSAGE_LENGTH)
 
1073
            {
 
1074
              DEBUG ("D-Bus message is too large to be valid, closing tube");
 
1075
              salut_tube_iface_close (SALUT_TUBE_IFACE (tube));
 
1076
              return;
 
1077
            }
 
1078
 
 
1079
          g_assert (priv->reassembly_bytes_needed != 0);
 
1080
          DEBUG ("We need %" G_GINT32_FORMAT " bytes for the next full "
 
1081
              "message", priv->reassembly_bytes_needed);
 
1082
        }
 
1083
    }
 
1084
  else
 
1085
    {
 
1086
      /* MUC bytestreams are message-boundary preserving, which is necessary,
 
1087
       * because we can't assume we started at the beginning */
 
1088
      g_assert (GIBBER_IS_BYTESTREAM_MUC (priv->bytestream));
 
1089
      message_received (tube, sender, data->str, data->len);
 
1090
    }
891
1091
}
892
1092
 
893
1093
SalutTubeDBus *
899
1099
                     TpHandle initiator,
900
1100
                     const gchar *service,
901
1101
                     GHashTable *parameters,
902
 
                     const gchar *stream_id,
903
 
                     guint id)
 
1102
                     guint id,
 
1103
                     GibberBytestreamIface *bytestream)
904
1104
{
905
 
  return g_object_new (SALUT_TYPE_TUBE_DBUS,
 
1105
  SalutTubeDBus *tube = g_object_new (SALUT_TYPE_TUBE_DBUS,
906
1106
      "connection", conn,
907
1107
      "handle", handle,
908
1108
      "handle-type", handle_type,
911
1111
      "initiator", initiator,
912
1112
      "service", service,
913
1113
      "parameters", parameters,
914
 
      "stream-id", stream_id,
915
1114
      "id", id,
916
1115
      NULL);
 
1116
 
 
1117
  if (bytestream != NULL)
 
1118
    g_object_set (tube, "bytestream", bytestream, NULL);
 
1119
 
 
1120
  return tube;
917
1121
}
918
1122
 
919
1123
/*
921
1125
 *
922
1126
 * Implements salut_tube_iface_accept on SalutTubeIface
923
1127
 */
924
 
static void
925
 
salut_tube_dbus_accept (SalutTubeIface *tube)
 
1128
static gboolean
 
1129
salut_tube_dbus_accept (SalutTubeIface *tube,
 
1130
                        GError **error)
926
1131
{
927
1132
  SalutTubeDBus *self = SALUT_TUBE_DBUS (tube);
928
1133
  SalutTubeDBusPrivate *priv = SALUT_TUBE_DBUS_GET_PRIVATE (self);
929
 
  GibberBytestreamIBBState state;
930
 
  gchar *stream_init_id;
 
1134
  GibberBytestreamState state;
931
1135
 
932
1136
  g_assert (priv->bytestream != NULL);
933
1137
 
935
1139
      "state", &state,
936
1140
      NULL);
937
1141
 
938
 
  if (state != GIBBER_BYTESTREAM_IBB_STATE_LOCAL_PENDING)
939
 
    return;
940
 
 
941
 
  g_object_get (priv->bytestream,
942
 
      "stream-init-id", &stream_init_id,
943
 
      NULL);
944
 
 
945
 
  if (stream_init_id != NULL)
 
1142
  if (state != GIBBER_BYTESTREAM_STATE_LOCAL_PENDING)
 
1143
    return TRUE;
 
1144
 
 
1145
  if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
946
1146
    {
947
 
      /* Bytestream was created using a SI request so
948
 
       * we have to accept it */
949
 
#if 0
950
 
      LmMessage *msg;
951
 
      LmMessageNode *si, *tube_node;
952
 
 
953
 
      DEBUG ("accept the SI request");
954
 
 
955
 
      msg = salut_bytestream_ibb_make_accept_iq (priv->bytestream);
956
 
      if (msg == NULL)
957
 
        {
958
 
          DEBUG ("can't create SI accept IQ. Close the bytestream");
959
 
          gibber_bytestream_ibb_close (priv->bytestream);
960
 
          return;
961
 
        }
962
 
 
963
 
      si = lm_message_node_get_child_with_namespace (msg->node, "si",
964
 
          NS_SI);
965
 
      g_assert (si != NULL);
966
 
 
967
 
      tube_node = lm_message_node_add_child (si, "tube", "");
968
 
      lm_message_node_set_attribute (tube_node, "xmlns", NS_SI_TUBES_OLD);
969
 
 
970
 
      lm_message_node_add_child (tube_node, "dbus-name",
971
 
          priv->dbus_local_name);
972
 
 
973
 
      salut_bytestream_ibb_accept (priv->bytestream, msg);
974
 
 
975
 
      lm_message_unref (msg);
976
 
      g_free (stream_init_id);
977
 
#endif
 
1147
      /* TODO: SI reply */
978
1148
    }
979
1149
  else
980
1150
    {
981
1151
      /* No SI so the bytestream is open */
982
1152
      DEBUG ("no SI, bytestream open");
983
1153
      g_object_set (priv->bytestream,
984
 
          "state", GIBBER_BYTESTREAM_IBB_STATE_OPEN,
 
1154
          "state", GIBBER_BYTESTREAM_STATE_OPEN,
985
1155
          NULL);
986
1156
    }
 
1157
 
 
1158
  return TRUE;
987
1159
}
988
1160
 
989
1161
/*
999
1171
 
1000
1172
  if (priv->bytestream != NULL)
1001
1173
    {
1002
 
      gibber_bytestream_ibb_close (priv->bytestream);
 
1174
      gibber_bytestream_iface_close (priv->bytestream, NULL);
1003
1175
    }
1004
1176
  else
1005
1177
    {
1015
1187
 
1016
1188
static void
1017
1189
salut_tube_dbus_add_bytestream (SalutTubeIface *tube,
1018
 
                                GibberBytestreamIBB *bytestream)
 
1190
                                GibberBytestreamIface *bytestream)
1019
1191
{
1020
1192
  DEBUG ("D-Bus doesn't support extra bytestream");
1021
 
  gibber_bytestream_ibb_close (bytestream);
 
1193
  gibber_bytestream_iface_close (bytestream, NULL);
 
1194
}
 
1195
 
 
1196
gboolean
 
1197
salut_tube_dbus_add_name (SalutTubeDBus *self,
 
1198
                         TpHandle handle,
 
1199
                         const gchar *name)
 
1200
{
 
1201
  SalutTubeDBusPrivate *priv = SALUT_TUBE_DBUS_GET_PRIVATE (self);
 
1202
  TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
 
1203
      (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
 
1204
 
 
1205
  g_assert (priv->handle_type == TP_HANDLE_TYPE_ROOM);
 
1206
 
 
1207
  if (g_hash_table_lookup (priv->dbus_names, GUINT_TO_POINTER (handle))
 
1208
      != NULL)
 
1209
    {
 
1210
      DEBUG ("contact %d has already announced his D-Bus name", handle);
 
1211
      return FALSE;
 
1212
    }
 
1213
 
 
1214
  if (g_str_has_prefix (name, ":2."))
 
1215
    {
 
1216
      gchar *supposed_name;
 
1217
      const gchar *contact_name;
 
1218
 
 
1219
      contact_name = tp_handle_inspect (contact_repo, handle);
 
1220
      supposed_name = generate_dbus_unique_name (contact_name);
 
1221
 
 
1222
      if (tp_strdiff (name, supposed_name))
 
1223
        {
 
1224
          DEBUG ("contact %s announces %s as D-Bus name but it should be %s",
 
1225
              contact_name, name, supposed_name);
 
1226
          g_free (supposed_name);
 
1227
          return FALSE;
 
1228
        }
 
1229
      g_free (supposed_name);
 
1230
    }
 
1231
 
 
1232
  g_hash_table_insert (priv->dbus_names, GUINT_TO_POINTER (handle),
 
1233
      g_strdup (name));
 
1234
  tp_handle_ref (contact_repo, handle);
 
1235
 
 
1236
  return TRUE;
 
1237
}
 
1238
 
 
1239
gboolean
 
1240
salut_tube_dbus_remove_name (SalutTubeDBus *self,
 
1241
                             TpHandle handle)
 
1242
{
 
1243
  SalutTubeDBusPrivate *priv = SALUT_TUBE_DBUS_GET_PRIVATE (self);
 
1244
  TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
 
1245
      (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
 
1246
  const gchar *name;
 
1247
 
 
1248
  g_assert (priv->handle_type == TP_HANDLE_TYPE_ROOM);
 
1249
 
 
1250
  name = g_hash_table_lookup (priv->dbus_names, GUINT_TO_POINTER (handle));
 
1251
  if (name == NULL)
 
1252
    return FALSE;
 
1253
 
 
1254
  g_hash_table_remove (priv->dbus_names, GUINT_TO_POINTER (handle));
 
1255
 
 
1256
  tp_handle_unref (contact_repo, handle);
 
1257
  return TRUE;
 
1258
}
 
1259
 
 
1260
gboolean
 
1261
salut_tube_dbus_handle_in_names (SalutTubeDBus *self,
 
1262
                                 TpHandle handle)
 
1263
{
 
1264
  SalutTubeDBusPrivate *priv = SALUT_TUBE_DBUS_GET_PRIVATE (self);
 
1265
 
 
1266
  g_assert (priv->handle_type == TP_HANDLE_TYPE_ROOM);
 
1267
 
 
1268
  return (g_hash_table_lookup (priv->dbus_names, GUINT_TO_POINTER (handle))
 
1269
      != NULL);
1022
1270
}
1023
1271
 
1024
1272
static void