1 /*
2 * tube-dbus.c - Source for GabbleTubeDBus
3 * Copyright (C) 2007-2008 Collabora Ltd.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 #include "config.h"
21 #include "tube-dbus.h"
22
23 #include <string.h>
24 #include <errno.h>
25
26 #include <glib/gstdio.h>
27 #include <dbus/dbus-glib.h>
28 #include <dbus/dbus-glib-lowlevel.h>
29 #include <wocky/wocky.h>
30 #include <telepathy-glib/telepathy-glib.h>
31 #include <telepathy-glib/telepathy-glib-dbus.h>
32
33 #include "extensions/extensions.h"
34
35 #define DEBUG_FLAG GABBLE_DEBUG_TUBES
36
37 #include "bytestream-factory.h"
38 #include "bytestream-ibb.h"
39 #include "bytestream-iface.h"
40 #include "connection.h"
41 #include "debug.h"
42 #include "disco.h"
43 #include "gabble-signals-marshal.h"
44 #include "muc-tube-dbus.h"
45 #include "namespaces.h"
46 #include "presence-cache.h"
47 #include "tube-iface.h"
48 #include "util.h"
49
50 /* When we receive D-Bus messages to be delivered to the application and the
51 * application is not yet connected to the D-Bus tube, theses D-Bus messages
52 * are queued and delivered when the application connects to the D-Bus tube.
53 *
54 * If the application never connects, there is a risk that the contact sends
55 * too many messages and eat all the memory. To avoid this, there is an
56 * arbitrary limit on the queue size set to 4MB. */
57 #define MAX_QUEUE_SIZE (4096*1024)
58
59 static void tube_iface_init (gpointer g_iface, gpointer iface_data);
60 static void dbustube_iface_init (gpointer g_iface, gpointer iface_data);
61
62 G_DEFINE_TYPE_WITH_CODE (GabbleTubeDBus, gabble_tube_dbus,
63 TP_TYPE_BASE_CHANNEL,
64 G_IMPLEMENT_INTERFACE (GABBLE_TYPE_TUBE_IFACE, tube_iface_init);
65 G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_DBUS_TUBE,
66 dbustube_iface_init);
67 G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_TUBE,
68 NULL);
69 G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_GROUP,
70 tp_external_group_mixin_iface_init);
71 );
72
73 static const gchar * const gabble_tube_dbus_channel_allowed_properties[] = {
74 TP_IFACE_CHANNEL ".TargetHandle",
75 TP_IFACE_CHANNEL ".TargetID",
76 TP_IFACE_CHANNEL_TYPE_DBUS_TUBE ".ServiceName",
77 NULL
78 };
79
80 /* signals */
81 enum
82 {
83 OPENED,
84 CLOSED,
85 OFFERED,
86 LAST_SIGNAL
87 };
88
89 static guint signals[LAST_SIGNAL] = {0};
90
91 /* properties */
92 enum
93 {
94 PROP_SELF_HANDLE = 1,
95 PROP_ID,
96 PROP_BYTESTREAM,
97 PROP_STREAM_ID,
98 PROP_TYPE,
99 PROP_SERVICE,
100 PROP_PARAMETERS,
101 PROP_STATE,
102 PROP_DBUS_ADDRESS,
103 PROP_DBUS_NAME,
104 PROP_DBUS_NAMES,
105 PROP_MUC,
106 PROP_SUPPORTED_ACCESS_CONTROLS,
107 LAST_PROPERTY
108 };
109
110 struct _GabbleTubeDBusPrivate
111 {
112 TpHandle self_handle;
113 guint64 id;
114 GabbleBytestreamIface *bytestream;
115 gchar *stream_id;
116 gchar *service;
117 GHashTable *parameters;
118 GabbleMucChannel *muc;
119 TpSocketAccessControl access_control;
120 /* GArray of guint */
121 GArray *supported_access_controls;
122
123 /* For outgoing tubes, TRUE if the offer has been sent over the network. For
124 * incoming tubes, always TRUE.
125 */
126 gboolean offered;
127
128 /* our unique D-Bus name on the virtual tube bus (NULL for 1-1 D-Bus tubes)*/
129 gchar *dbus_local_name;
130 /* the address that we are listening for D-Bus connections on */
131 gchar *dbus_srv_addr;
132 /* the path of the UNIX socket used by the D-Bus server */
133 gchar *socket_path;
134 /* the server that's listening on dbus_srv_addr */
135 DBusServer *dbus_srv;
136 /* the connection to dbus_srv from a local client, or NULL */
137 DBusConnection *dbus_conn;
138 /* the queue of D-Bus messages to be delivered to a local client when it
139 * will connect */
140 GSList *dbus_msg_queue;
141 /* current size of the queue in bytes. The maximum is MAX_QUEUE_SIZE */
142 unsigned long dbus_msg_queue_size;
143 /* mapping of contact handle -> D-Bus name (empty for 1-1 D-Bus tubes) */
144 GHashTable *dbus_names;
145 /* mapping of D-Bus name -> contact handle */
146 GHashTable *dbus_name_to_handle;
147
148 /* Message reassembly buffer (CONTACT tubes only) */
149 GString *reassembly_buffer;
150 /* Number of bytes that will be in the next message, 0 if unknown */
151 guint32 reassembly_bytes_needed;
152
153 gboolean dispose_has_run;
154 };
155
156 #define GABBLE_TUBE_DBUS_GET_PRIVATE(obj) ((obj)->priv)
157
158 static GPtrArray *
gabble_tube_dbus_get_interfaces(TpBaseChannel * base)159 gabble_tube_dbus_get_interfaces (TpBaseChannel *base)
160 {
161 GPtrArray *interfaces;
162
163 interfaces = TP_BASE_CHANNEL_CLASS (
164 gabble_tube_dbus_parent_class)->get_interfaces (base);
165
166 g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_TUBE);
167
168 return interfaces;
169 }
170
171 static void data_received_cb (GabbleBytestreamIface *stream, TpHandle sender,
172 GString *data, gpointer user_data);
173
174 /*
175 * Characters used are permissible both in filenames and in D-Bus names. (See
176 * D-Bus specification for restrictions.)
177 */
178 static void
generate_ascii_string(guint len,gchar * buf)179 generate_ascii_string (guint len,
180 gchar *buf)
181 {
182 const gchar *chars =
183 "0123456789"
184 "abcdefghijklmnopqrstuvwxyz"
185 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
186 "_-";
187 guint i;
188
189 for (i = 0; i < len; i++)
190 buf[i] = chars[g_random_int_range (0, 64)];
191 }
192
193 static DBusHandlerResult
filter_cb(DBusConnection * conn,DBusMessage * msg,void * user_data)194 filter_cb (DBusConnection *conn,
195 DBusMessage *msg,
196 void *user_data)
197 {
198 GabbleTubeDBus *tube = GABBLE_TUBE_DBUS (user_data);
199 GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (tube);
200 gchar *marshalled = NULL;
201 gint len;
202
203 if (dbus_message_get_type (msg) == DBUS_MESSAGE_TYPE_SIGNAL &&
204 !tp_strdiff (dbus_message_get_interface (msg),
205 "org.freedesktop.DBus.Local") &&
206 !tp_strdiff (dbus_message_get_member (msg), "Disconnected"))
207 {
208 /* connection was disconnected */
209 DEBUG ("connection was disconnected");
210 dbus_connection_close (priv->dbus_conn);
211 tp_clear_pointer (&priv->dbus_conn, dbus_connection_unref);
212 goto out;
213 }
214
215 if (priv->dbus_local_name != NULL)
216 {
217 if (!dbus_message_set_sender (msg, priv->dbus_local_name))
218 DEBUG ("dbus_message_set_sender failed");
219 }
220
221 if (!dbus_message_marshal (msg, &marshalled, &len))
222 goto out;
223
224 if (GABBLE_IS_BYTESTREAM_MUC (priv->bytestream))
225 {
226 /* This bytestream support direct send */
227 const gchar *dest;
228
229 dest = dbus_message_get_destination (msg);
230
231 if (dest != NULL)
232 {
233 TpHandle handle;
234
235 handle = GPOINTER_TO_UINT (g_hash_table_lookup (
236 priv->dbus_name_to_handle, dest));
237
238 if (handle == 0)
239 {
240 DEBUG ("Unknown D-Bus name: %s", dest);
241 goto out;
242 }
243
244 gabble_bytestream_muc_send_to (
245 GABBLE_BYTESTREAM_MUC (priv->bytestream), handle, len,
246 marshalled);
247
248 goto out;
249 }
250 }
251
252 gabble_bytestream_iface_send (priv->bytestream, len, marshalled);
253
254 out:
255 if (marshalled != NULL)
256 g_free (marshalled);
257
258 return DBUS_HANDLER_RESULT_HANDLED;
259 }
260
261 static dbus_bool_t
allow_all_connections(DBusConnection * conn,unsigned long uid,void * data)262 allow_all_connections (DBusConnection *conn,
263 unsigned long uid,
264 void *data)
265 {
266 return TRUE;
267 }
268
269 static void
new_connection_cb(DBusServer * server,DBusConnection * conn,void * data)270 new_connection_cb (DBusServer *server,
271 DBusConnection *conn,
272 void *data)
273 {
274 GabbleTubeDBus *tube = GABBLE_TUBE_DBUS (data);
275 GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (tube);
276 guint32 serial;
277 GSList *i;
278
279 if (priv->dbus_conn != NULL)
280 /* we already have a connection; drop this new one */
281 /* return without reffing conn means it will be dropped */
282 return;
283
284 DEBUG ("got connection");
285
286 dbus_connection_ref (conn);
287 dbus_connection_setup_with_g_main (conn, NULL);
288 dbus_connection_add_filter (conn, filter_cb, tube, NULL);
289 priv->dbus_conn = conn;
290
291 if (priv->access_control == TP_SOCKET_ACCESS_CONTROL_LOCALHOST)
292 {
293 /* By default libdbus use Credentials access control. If user wants
294 * to use the Localhost access control, we need to bypass this check. */
295 dbus_connection_set_unix_user_function (conn, allow_all_connections,
296 NULL, NULL);
297 }
298
299 /* We may have received messages to deliver before the local connection is
300 * established. Theses messages are kept in the dbus_msg_queue list and are
301 * delivered as soon as we get the connection. */
302 DEBUG ("%u messages in the queue (%lu bytes)",
303 g_slist_length (priv->dbus_msg_queue), priv->dbus_msg_queue_size);
304 priv->dbus_msg_queue = g_slist_reverse (priv->dbus_msg_queue);
305 for (i = priv->dbus_msg_queue; i != NULL; i = g_slist_delete_link (i, i))
306 {
307 DBusMessage *msg = i->data;
308 DEBUG ("delivering queued message from '%s' to '%s' on the "
309 "new connection",
310 dbus_message_get_sender (msg),
311 dbus_message_get_destination (msg));
312 dbus_connection_send (priv->dbus_conn, msg, &serial);
313 dbus_message_unref (msg);
314 }
315 priv->dbus_msg_queue = NULL;
316 priv->dbus_msg_queue_size = 0;
317 }
318
319 static void
gabble_tube_dbus_close(TpBaseChannel * base)320 gabble_tube_dbus_close (TpBaseChannel *base)
321 {
322 GabbleTubeDBus *self = GABBLE_TUBE_DBUS (base);
323 GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self);
324
325 /* Take a ref to ourselves as when we emit tube-closed
326 * GabbleTubesChannel will drop our last ref but we still need to
327 * declare ourselves as destroyed. This is rubbish, but will
328 * disappear when we finally remove the Tubes channel type.. */
329 g_object_ref (base);
330
331 if (priv->bytestream != NULL)
332 gabble_bytestream_iface_close (priv->bytestream, NULL);
333 else
334 g_signal_emit (G_OBJECT (self), signals[CLOSED],0);
335
336 tp_base_channel_destroyed (base);
337
338 g_object_unref (base);
339 }
340
341 /* There is two step to enable receiving a D-Bus connection from the local
342 * application:
343 * - listen on the socket
344 * - add the socket in the mainloop
345 *
346 * We need to know the socket path to return from the AcceptDBusTube D-Bus
347 * call but the socket in the mainloop must be added only when we are ready
348 * to receive connections, that is when the bytestream is fully open with the
349 * remote contact.
350 *
351 * See also Bug 13891:
352 * https://bugs.freedesktop.org/show_bug.cgi?id=13891
353 * */
354 static gboolean
create_dbus_server(GabbleTubeDBus * self,GError ** err)355 create_dbus_server (GabbleTubeDBus *self,
356 GError **err)
357 {
358 #define SERVER_LISTEN_MAX_TRIES 5
359 GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self);
360 guint i;
361
362 if (priv->dbus_srv != NULL)
363 return TRUE;
364
365 for (i = 0; i < SERVER_LISTEN_MAX_TRIES; i++)
366 {
367 gchar suffix[8];
368 DBusError error;
369
370 g_free (priv->dbus_srv_addr);
371 g_free (priv->socket_path);
372
373 generate_ascii_string (8, suffix);
374 priv->socket_path = g_strdup_printf ("%s/dbus-gabble-%.8s",
375 g_get_tmp_dir (), suffix);
376 priv->dbus_srv_addr = g_strdup_printf ("unix:path=%s",
377 priv->socket_path);
378
379 dbus_error_init (&error);
380 priv->dbus_srv = dbus_server_listen (priv->dbus_srv_addr, &error);
381
382 if (priv->dbus_srv != NULL)
383 break;
384
385 DEBUG ("dbus_server_listen failed (try %u): %s: %s", i, error.name,
386 error.message);
387 dbus_error_free (&error);
388 }
389
390 if (priv->dbus_srv == NULL)
391 {
392 DEBUG ("all attempts failed. Close the tube");
393
394 g_free (priv->dbus_srv_addr);
395 priv->dbus_srv_addr = NULL;
396
397 g_free (priv->socket_path);
398 priv->socket_path = NULL;
399
400 g_set_error (err, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
401 "Can't create D-Bus server");
402 return FALSE;
403 }
404
405 DEBUG ("listening on %s", priv->dbus_srv_addr);
406
407 dbus_server_set_new_connection_function (priv->dbus_srv, new_connection_cb,
408 self, NULL);
409
410 return TRUE;
411 }
412
413 static void
tube_dbus_open(GabbleTubeDBus * self)414 tube_dbus_open (GabbleTubeDBus *self)
415 {
416 GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self);
417 TpBaseChannel *base = TP_BASE_CHANNEL (self);
418 TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base);
419
420 g_signal_connect (priv->bytestream, "data-received",
421 G_CALLBACK (data_received_cb), self);
422
423 /* TODO: we should remove this call once muc D-Bus tube new API are
424 * implemented as the server should already exist. */
425 if (!create_dbus_server (self, NULL))
426 tp_base_channel_close (TP_BASE_CHANNEL (self));
427
428 if (priv->dbus_srv != NULL)
429 {
430 dbus_server_setup_with_g_main (priv->dbus_srv, NULL);
431 }
432
433 if (cls->target_handle_type == TP_HANDLE_TYPE_ROOM)
434 {
435 /* add yourself in dbus names */
436 gabble_tube_dbus_add_name (self, priv->self_handle,
437 priv->dbus_local_name);
438
439 gabble_muc_channel_send_presence (priv->muc);
440 }
441 }
442
443 static void
gabble_tube_dbus_init(GabbleTubeDBus * self)444 gabble_tube_dbus_init (GabbleTubeDBus *self)
445 {
446 GabbleTubeDBusPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
447 GABBLE_TYPE_TUBE_DBUS, GabbleTubeDBusPrivate);
448
449 self->priv = priv;
450 }
451
452 static TpTubeChannelState
get_tube_state(GabbleTubeDBus * self)453 get_tube_state (GabbleTubeDBus *self)
454 {
455 GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self);
456 GabbleBytestreamState bytestream_state;
457
458 if (!priv->offered)
459 return TP_TUBE_CHANNEL_STATE_NOT_OFFERED;
460
461 if (priv->bytestream == NULL)
462 /* bytestream not yet created as we're waiting for the SI reply */
463 return TP_TUBE_CHANNEL_STATE_REMOTE_PENDING;
464
465 g_object_get (priv->bytestream, "state", &bytestream_state, NULL);
466
467 switch (bytestream_state)
468 {
469 case GABBLE_BYTESTREAM_STATE_OPEN:
470 return TP_TUBE_CHANNEL_STATE_OPEN;
471 break;
472 case GABBLE_BYTESTREAM_STATE_LOCAL_PENDING:
473 case GABBLE_BYTESTREAM_STATE_ACCEPTED:
474 return TP_TUBE_CHANNEL_STATE_LOCAL_PENDING;
475 break;
476 case GABBLE_BYTESTREAM_STATE_INITIATING:
477 return TP_TUBE_CHANNEL_STATE_REMOTE_PENDING;
478 break;
479 default:
480 g_return_val_if_reached (0);
481 }
482 }
483
484 static void
bytestream_state_changed_cb(GabbleBytestreamIface * bytestream,GabbleBytestreamState state,gpointer user_data)485 bytestream_state_changed_cb (GabbleBytestreamIface *bytestream,
486 GabbleBytestreamState state,
487 gpointer user_data)
488 {
489 GabbleTubeDBus *self = GABBLE_TUBE_DBUS (user_data);
490 GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self);
491 TpBaseChannel *base = TP_BASE_CHANNEL (self);
492 TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base);
493
494 if (state == GABBLE_BYTESTREAM_STATE_CLOSED)
495 {
496 tp_clear_object (&priv->bytestream);
497 g_signal_emit (G_OBJECT (self), signals[CLOSED], 0);
498
499 if (cls->target_handle_type == TP_HANDLE_TYPE_ROOM)
500 gabble_muc_channel_send_presence (priv->muc);
501 }
502 else if (state == GABBLE_BYTESTREAM_STATE_OPEN)
503 {
504 tube_dbus_open (self);
505
506 tp_svc_channel_interface_tube_emit_tube_channel_state_changed (self,
507 TP_TUBE_CHANNEL_STATE_OPEN);
508
509 g_signal_emit (G_OBJECT (self), signals[OPENED], 0);
510 }
511 }
512
513 static void
gabble_tube_dbus_dispose(GObject * object)514 gabble_tube_dbus_dispose (GObject *object)
515 {
516 GabbleTubeDBus *self = GABBLE_TUBE_DBUS (object);
517 GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self);
518
519 DEBUG ("called");
520
521 if (priv->dispose_has_run)
522 return;
523
524 priv->dispose_has_run = TRUE;
525
526 if (priv->bytestream != NULL)
527 gabble_bytestream_iface_close (priv->bytestream, NULL);
528
529 if (priv->dbus_conn != NULL)
530 dbus_connection_close (priv->dbus_conn);
531
532 tp_clear_pointer (&priv->dbus_conn, dbus_connection_unref);
533
534 if (priv->dbus_srv != NULL)
535 dbus_server_disconnect (priv->dbus_srv);
536
537 tp_clear_pointer (&priv->dbus_srv, dbus_server_unref);
538
539 if (priv->socket_path != NULL)
540 {
541 if (g_unlink (priv->socket_path) != 0)
542 {
543 DEBUG ("unlink of %s failed: %s", priv->socket_path,
544 g_strerror (errno));
545 }
546 }
547
548 if (priv->dbus_msg_queue != NULL)
549 {
550 GSList *i;
551 for (i = priv->dbus_msg_queue; i != NULL; i = g_slist_delete_link (i, i))
552 {
553 DBusMessage *msg = i->data;
554 dbus_message_unref (msg);
555 }
556 priv->dbus_msg_queue = NULL;
557 priv->dbus_msg_queue_size = 0;
558 }
559
560 tp_clear_pointer (&priv->dbus_srv_addr, g_free);
561 tp_clear_pointer (&priv->socket_path, g_free);
562 tp_clear_pointer (&priv->dbus_local_name, g_free);
563 tp_clear_pointer (&priv->dbus_names, g_hash_table_unref);
564 tp_clear_pointer (&priv->dbus_name_to_handle, g_hash_table_unref);
565
566 if (priv->reassembly_buffer)
567 g_string_free (priv->reassembly_buffer, TRUE);
568
569 if (G_OBJECT_CLASS (gabble_tube_dbus_parent_class)->dispose)
570 G_OBJECT_CLASS (gabble_tube_dbus_parent_class)->dispose (object);
571 }
572
573 static void
gabble_tube_dbus_finalize(GObject * object)574 gabble_tube_dbus_finalize (GObject *object)
575 {
576 GabbleTubeDBus *self = GABBLE_TUBE_DBUS (object);
577 GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self);
578
579 g_free (priv->stream_id);
580 g_free (priv->service);
581 g_hash_table_unref (priv->parameters);
582 g_array_unref (priv->supported_access_controls);
583
584 if (priv->muc != NULL)
585 tp_external_group_mixin_finalize (object);
586
587 G_OBJECT_CLASS (gabble_tube_dbus_parent_class)->finalize (object);
588 }
589
590 static void
gabble_tube_dbus_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)591 gabble_tube_dbus_get_property (GObject *object,
592 guint property_id,
593 GValue *value,
594 GParamSpec *pspec)
595 {
596 GabbleTubeDBus *self = GABBLE_TUBE_DBUS (object);
597 GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self);
598
599 switch (property_id)
600 {
601 case PROP_SELF_HANDLE:
602 g_value_set_uint (value, priv->self_handle);
603 break;
604 case PROP_ID:
605 g_value_set_uint64 (value, priv->id);
606 break;
607 case PROP_BYTESTREAM:
608 g_value_set_object (value, priv->bytestream);
609 break;
610 case PROP_STREAM_ID:
611 g_value_set_string (value, priv->stream_id);
612 break;
613 case PROP_TYPE:
614 g_value_set_uint (value, TP_TUBE_TYPE_DBUS);
615 break;
616 case PROP_SERVICE:
617 g_value_set_string (value, priv->service);
618 break;
619 case PROP_PARAMETERS:
620 g_value_set_boxed (value, priv->parameters);
621 break;
622 case PROP_STATE:
623 g_value_set_uint (value, get_tube_state (self));
624 break;
625 case PROP_DBUS_ADDRESS:
626 g_value_set_string (value, priv->dbus_srv_addr);
627 break;
628 case PROP_DBUS_NAME:
629 g_value_set_string (value, priv->dbus_local_name);
630 break;
631 case PROP_DBUS_NAMES:
632 g_value_set_boxed (value, priv->dbus_names);
633 break;
634 case PROP_MUC:
635 g_value_set_object (value, priv->muc);
636 break;
637 case PROP_SUPPORTED_ACCESS_CONTROLS:
638 g_value_set_boxed (value, priv->supported_access_controls);
639 break;
640 default:
641 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
642 break;
643 }
644 }
645
646 static void
gabble_tube_dbus_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)647 gabble_tube_dbus_set_property (GObject *object,
648 guint property_id,
649 const GValue *value,
650 GParamSpec *pspec)
651 {
652 GabbleTubeDBus *self = GABBLE_TUBE_DBUS (object);
653 GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self);
654
655 switch (property_id)
656 {
657 case PROP_SELF_HANDLE:
658 priv->self_handle = g_value_get_uint (value);
659 break;
660 case PROP_ID:
661 priv->id = g_value_get_uint64 (value);
662 break;
663 case PROP_BYTESTREAM:
664 if (priv->bytestream == NULL)
665 {
666 GabbleBytestreamState state;
667
668 priv->bytestream = g_value_get_object (value);
669 g_object_ref (priv->bytestream);
670
671 g_object_get (priv->bytestream, "state", &state, NULL);
672 if (state == GABBLE_BYTESTREAM_STATE_OPEN)
673 {
674 tube_dbus_open (self);
675 }
676
677 g_signal_connect (priv->bytestream, "state-changed",
678 G_CALLBACK (bytestream_state_changed_cb), self);
679 }
680 break;
681 case PROP_STREAM_ID:
682 g_free (priv->stream_id);
683 priv->stream_id = g_value_dup_string (value);
684 break;
685 case PROP_SERVICE:
686 g_free (priv->service);
687 priv->service = g_value_dup_string (value);
688 break;
689 case PROP_PARAMETERS:
690 if (priv->parameters != NULL)
691 g_hash_table_unref (priv->parameters);
692 priv->parameters = g_value_dup_boxed (value);
693 break;
694 case PROP_MUC:
695 priv->muc = g_value_get_object (value);
696 break;
697 default:
698 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
699 break;
700 }
701 }
702
703 static void
gabble_tube_dbus_constructed(GObject * obj)704 gabble_tube_dbus_constructed (GObject *obj)
705 {
706 GabbleTubeDBus *self = GABBLE_TUBE_DBUS (obj);
707 GabbleTubeDBusPrivate *priv = self->priv;
708 TpBaseChannel *base = TP_BASE_CHANNEL (obj);
709 TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base);
710 TpBaseConnection *base_conn = tp_base_channel_get_connection (base);
711 GabbleConnection *conn = GABBLE_CONNECTION (base_conn);
712 TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
713 base_conn, TP_HANDLE_TYPE_CONTACT);
714 guint access_control;
715
716 void (*chain_up) (GObject *) =
717 ((GObjectClass *) gabble_tube_dbus_parent_class)->constructed;
718
719 if (chain_up != NULL)
720 chain_up (obj);
721
722 priv->dbus_names = g_hash_table_new_full (g_direct_hash, g_direct_equal,
723 NULL, g_free);
724
725 g_assert (priv->self_handle != 0);
726 if (cls->target_handle_type == TP_HANDLE_TYPE_ROOM)
727 {
728 /* We have to create a pseudo-IBB bytestream that will be
729 * used by this MUC tube to communicate.
730 */
731 GabbleBytestreamMuc *bytestream;
732 gchar *nick;
733
734 g_assert (priv->stream_id != NULL);
735
736 priv->dbus_name_to_handle = g_hash_table_new_full (g_str_hash,
737 g_str_equal, NULL, NULL);
738
739 g_assert (wocky_decode_jid (
740 tp_handle_inspect (contact_repo, priv->self_handle),
741 NULL, NULL, &nick));
742 g_assert (nick != NULL);
743
744 priv->dbus_local_name = _gabble_generate_dbus_unique_name (nick);
745
746 DEBUG ("local name: %s", priv->dbus_local_name);
747
748 bytestream = gabble_bytestream_factory_create_muc (
749 conn->bytestream_factory,
750 tp_base_channel_get_target_handle (base),
751 priv->stream_id,
752 GABBLE_BYTESTREAM_STATE_LOCAL_PENDING);
753
754 g_object_set (self, "bytestream", bytestream, NULL);
755
756 g_free (nick);
757
758 g_assert (priv->muc != NULL);
759 tp_external_group_mixin_init (obj, (GObject *) priv->muc);
760 }
761 else
762 {
763 /* The D-Bus names mapping is used in muc tubes only */
764 priv->dbus_local_name = NULL;
765 priv->dbus_name_to_handle = NULL;
766
767 /* For contact (IBB) tubes we need to be able to reassemble messages. */
768 priv->reassembly_buffer = g_string_new ("");
769 priv->reassembly_bytes_needed = 0;
770
771 g_assert (priv->muc == NULL);
772
773 if (tp_base_channel_is_requested (base))
774 {
775 /* We created this outgoing 1-1 D-Bus tube and so will need SOCKS5
776 * proxies when we'll offer it. */
777 gabble_bytestream_factory_query_socks5_proxies (
778 conn->bytestream_factory);
779 }
780 }
781
782 /* Tube needs to be offered if we initiated AND requested it. Being
783 * the initiator is not enough as we could re-join a muc containing and old
784 * tube we created when we were in this room some time ago. In that case, we
785 * have to accept it if we want to re-join the tube. */
786 if (tp_base_channel_get_initiator (base) == priv->self_handle &&
787 tp_base_channel_is_requested (base))
788 {
789 priv->offered = FALSE;
790 }
791 else
792 {
793 /* Incoming tubes have already been offered, as it were. */
794 priv->offered = TRUE;
795 }
796
797 /* default access control is Credentials as that's the one used by the old
798 * tube API */
799 priv->access_control = TP_SOCKET_ACCESS_CONTROL_CREDENTIALS;
800
801 /* Set SupportedAccessesControl */
802 priv->supported_access_controls = g_array_sized_new (FALSE, FALSE,
803 sizeof (guint), 1);
804 access_control = TP_SOCKET_ACCESS_CONTROL_CREDENTIALS;
805 g_array_append_val (priv->supported_access_controls, access_control);
806 access_control = TP_SOCKET_ACCESS_CONTROL_LOCALHOST;
807 g_array_append_val (priv->supported_access_controls, access_control);
808 }
809
810 static void
gabble_tube_dbus_fill_immutable_properties(TpBaseChannel * chan,GHashTable * properties)811 gabble_tube_dbus_fill_immutable_properties (TpBaseChannel *chan,
812 GHashTable *properties)
813 {
814 TpBaseChannelClass *cls = TP_BASE_CHANNEL_CLASS (
815 gabble_tube_dbus_parent_class);
816
817 cls->fill_immutable_properties (chan, properties);
818
819 tp_dbus_properties_mixin_fill_properties_hash (
820 G_OBJECT (chan), properties,
821 TP_IFACE_CHANNEL_TYPE_DBUS_TUBE, "ServiceName",
822 TP_IFACE_CHANNEL_TYPE_DBUS_TUBE, "SupportedAccessControls",
823 NULL);
824
825 if (!tp_base_channel_is_requested (chan))
826 {
827 tp_dbus_properties_mixin_fill_properties_hash (
828 G_OBJECT (chan), properties,
829 TP_IFACE_CHANNEL_INTERFACE_TUBE, "Parameters",
830 NULL);
831 }
832 }
833
834 static gchar *
gabble_tube_dbus_get_object_path_suffix(TpBaseChannel * base)835 gabble_tube_dbus_get_object_path_suffix (TpBaseChannel *base)
836 {
837 GabbleTubeDBus *self = GABBLE_TUBE_DBUS (base);
838
839 return g_strdup_printf ("DBusTubeChannel/%u/%" G_GUINT64_FORMAT,
840 tp_base_channel_get_target_handle (base),
841 self->priv->id);
842 }
843
844 static void
gabble_tube_dbus_class_init(GabbleTubeDBusClass * gabble_tube_dbus_class)845 gabble_tube_dbus_class_init (GabbleTubeDBusClass *gabble_tube_dbus_class)
846 {
847 static TpDBusPropertiesMixinPropImpl dbus_tube_props[] = {
848 { "ServiceName", "service", NULL },
849 { "DBusNames", "dbus-names", NULL },
850 { "SupportedAccessControls", "supported-access-controls", NULL },
851 { NULL }
852 };
853 static TpDBusPropertiesMixinPropImpl tube_iface_props[] = {
854 { "Parameters", "parameters", NULL },
855 { "State", "state", NULL },
856 { NULL }
857 };
858 static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = {
859 { TP_IFACE_CHANNEL_TYPE_DBUS_TUBE,
860 tp_dbus_properties_mixin_getter_gobject_properties,
861 NULL,
862 dbus_tube_props,
863 },
864 { TP_IFACE_CHANNEL_INTERFACE_TUBE,
865 tp_dbus_properties_mixin_getter_gobject_properties,
866 NULL,
867 tube_iface_props,
868 },
869 { NULL }
870 };
871 GObjectClass *object_class = G_OBJECT_CLASS (gabble_tube_dbus_class);
872 TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS (gabble_tube_dbus_class);
873 GParamSpec *param_spec;
874
875 object_class->get_property = gabble_tube_dbus_get_property;
876 object_class->set_property = gabble_tube_dbus_set_property;
877 object_class->constructed = gabble_tube_dbus_constructed;
878 object_class->dispose = gabble_tube_dbus_dispose;
879 object_class->finalize = gabble_tube_dbus_finalize;
880
881 base_class->channel_type = TP_IFACE_CHANNEL_TYPE_DBUS_TUBE;
882 base_class->get_interfaces = gabble_tube_dbus_get_interfaces;
883 base_class->target_handle_type = TP_HANDLE_TYPE_CONTACT;
884 base_class->close = gabble_tube_dbus_close;
885 base_class->fill_immutable_properties =
886 gabble_tube_dbus_fill_immutable_properties;
887 base_class->get_object_path_suffix =
888 gabble_tube_dbus_get_object_path_suffix;
889
890 g_type_class_add_private (gabble_tube_dbus_class,
891 sizeof (GabbleTubeDBusPrivate));
892
893 g_object_class_override_property (object_class, PROP_SELF_HANDLE,
894 "self-handle");
895 g_object_class_override_property (object_class, PROP_ID,
896 "id");
897 g_object_class_override_property (object_class, PROP_TYPE,
898 "type");
899 g_object_class_override_property (object_class, PROP_SERVICE,
900 "service");
901 g_object_class_override_property (object_class, PROP_PARAMETERS,
902 "parameters");
903 g_object_class_override_property (object_class, PROP_STATE,
904 "state");
905
906 param_spec = g_param_spec_object (
907 "bytestream",
908 "Object implementing the GabbleBytestreamIface interface",
909 "Bytestream object used for streaming data for this"
910 "tube object.",
911 G_TYPE_OBJECT,
912 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
913 g_object_class_install_property (object_class, PROP_BYTESTREAM,
914 param_spec);
915
916 param_spec = g_param_spec_string (
917 "stream-id",
918 "stream id",
919 "The identifier of this tube's bytestream",
920 "",
921 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
922 g_object_class_install_property (object_class, PROP_STREAM_ID,
923 param_spec);
924
925 param_spec = g_param_spec_string (
926 "dbus-address",
927 "D-Bus address",
928 "The D-Bus address on which this tube will listen for connections",
929 "",
930 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
931 g_object_class_install_property (object_class, PROP_DBUS_ADDRESS,
932 param_spec);
933
934 param_spec = g_param_spec_string (
935 "dbus-name",
936 "D-Bus name",
937 "The local D-Bus name on the virtual bus (used for muc tubes only).",
938 "",
939 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
940 g_object_class_install_property (object_class, PROP_DBUS_NAME, param_spec);
941
942 param_spec = g_param_spec_boxed (
943 "dbus-names",
944 "D-Bus names",
945 "Mapping of contact handles to D-Bus names (used for muc tubes only).",
946 TP_HASH_TYPE_DBUS_TUBE_PARTICIPANTS,
947 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
948 g_object_class_install_property (object_class, PROP_DBUS_NAMES, param_spec);
949
950 param_spec = g_param_spec_object ("muc", "GabbleMucChannel object",
951 "Gabble text MUC channel corresponding to this Tube channel object, "
952 "if the handle type is ROOM.",
953 GABBLE_TYPE_MUC_CHANNEL,
954 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
955
956 g_object_class_install_property (object_class, PROP_MUC, param_spec);
957
958 param_spec = g_param_spec_boxed (
959 "supported-access-controls",
960 "Supported access-controls",
961 "GArray containing supported access controls.",
962 DBUS_TYPE_G_UINT_ARRAY,
963 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
964 g_object_class_install_property (object_class,
965 PROP_SUPPORTED_ACCESS_CONTROLS, param_spec);
966
967 signals[OPENED] =
968 g_signal_new ("tube-opened",
969 G_OBJECT_CLASS_TYPE (gabble_tube_dbus_class),
970 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
971 0,
972 NULL, NULL,
973 g_cclosure_marshal_VOID__VOID,
974 G_TYPE_NONE, 0);
975
976 signals[CLOSED] =
977 g_signal_new ("tube-closed",
978 G_OBJECT_CLASS_TYPE (gabble_tube_dbus_class),
979 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
980 0,
981 NULL, NULL,
982 g_cclosure_marshal_VOID__VOID,
983 G_TYPE_NONE, 0);
984
985 signals[OFFERED] =
986 g_signal_new ("tube-offered",
987 G_OBJECT_CLASS_TYPE (gabble_tube_dbus_class),
988 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
989 0,
990 NULL, NULL,
991 g_cclosure_marshal_VOID__VOID,
992 G_TYPE_NONE, 0);
993
994 gabble_tube_dbus_class->dbus_props_class.interfaces = prop_interfaces;
995 tp_dbus_properties_mixin_class_init (object_class,
996 G_STRUCT_OFFSET (GabbleTubeDBusClass, dbus_props_class));
997
998 tp_external_group_mixin_init_dbus_properties (object_class);
999 }
1000
1001 static void
bytestream_negotiate_cb(GabbleBytestreamIface * bytestream,WockyStanza * msg,GObject * object,gpointer user_data)1002 bytestream_negotiate_cb (GabbleBytestreamIface *bytestream,
1003 WockyStanza *msg,
1004 GObject *object,
1005 gpointer user_data)
1006 {
1007 GabbleTubeIface *tube = user_data;
1008
1009 if (bytestream == NULL)
1010 {
1011 /* Tube was declined by remote user. Close it */
1012 gabble_tube_iface_close (tube, TRUE);
1013 return;
1014 }
1015
1016 /* Tube was accepted by remote user */
1017
1018 g_object_set (tube,
1019 "bytestream", bytestream,
1020 NULL);
1021
1022 gabble_tube_iface_accept (tube, NULL);
1023 }
1024
1025 gboolean
gabble_tube_dbus_offer(GabbleTubeDBus * tube,GError ** error)1026 gabble_tube_dbus_offer (GabbleTubeDBus *tube,
1027 GError **error)
1028 {
1029 GabbleTubeDBusPrivate *priv = tube->priv;
1030 TpBaseChannel *base = TP_BASE_CHANNEL (tube);
1031 TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base);
1032 TpBaseConnection *base_conn = tp_base_channel_get_connection (base);
1033 GabbleConnection *conn = GABBLE_CONNECTION (base_conn);
1034
1035 if (priv->offered)
1036 {
1037 g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
1038 "Tube has already been offered");
1039 return FALSE;
1040 }
1041
1042 if (cls->target_handle_type == TP_HANDLE_TYPE_CONTACT)
1043 {
1044 TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
1045 base_conn, TP_HANDLE_TYPE_CONTACT);
1046 const gchar *jid, *resource;
1047 gchar *full_jid;
1048 GabblePresence *presence;
1049 WockyNode *tube_node, *si_node;
1050 WockyStanza *msg;
1051
1052 jid = tp_handle_inspect (contact_repo,
1053 tp_base_channel_get_target_handle (base));
1054 presence = gabble_presence_cache_get (conn->presence_cache,
1055 tp_base_channel_get_target_handle (base));
1056
1057 if (presence == NULL)
1058 {
1059 DEBUG ("can't find contact %s's presence", jid);
1060 g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
1061 "can't find contact %s's presence", jid);
1062 return FALSE;
1063 }
1064
1065 resource = gabble_presence_pick_resource_by_caps (presence, 0,
1066 gabble_capability_set_predicate_has, NS_TUBES);
1067
1068 if (resource == NULL)
1069 {
1070 DEBUG ("contact %s doesn't have tubes capabilities", jid);
1071 g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
1072 "contact %s doesn't have tubes capabilities", jid);
1073 return FALSE;
1074 }
1075
1076 full_jid = g_strdup_printf ("%s/%s", jid, resource);
1077 msg = gabble_bytestream_factory_make_stream_init_iq (full_jid,
1078 priv->stream_id, NS_TUBES);
1079 si_node = wocky_node_get_child_ns (
1080 wocky_stanza_get_top_node (msg), "si", NS_SI);
1081 g_assert (si_node != NULL);
1082
1083 tube_node = wocky_node_add_child_ns (si_node, "tube", NS_TUBES);
1084 gabble_tube_iface_publish_in_node (GABBLE_TUBE_IFACE (tube),
1085 base_conn, tube_node);
1086
1087 tube->priv->offered = TRUE;
1088 gabble_bytestream_factory_negotiate_stream (
1089 conn->bytestream_factory, msg, priv->stream_id,
1090 bytestream_negotiate_cb, tube, G_OBJECT (tube));
1091
1092 /* We don't create the bytestream of private D-Bus tube yet.
1093 * It will be when we'll receive the answer of the SI request */
1094 g_object_unref (msg);
1095 g_free (full_jid);
1096
1097 tp_svc_channel_interface_tube_emit_tube_channel_state_changed (tube,
1098 TP_TUBE_CHANNEL_STATE_REMOTE_PENDING);
1099 }
1100 else
1101 {
1102 tube->priv->offered = TRUE;
1103 g_object_set (priv->bytestream,
1104 "state", GABBLE_BYTESTREAM_STATE_OPEN,
1105 NULL);
1106
1107 gabble_muc_channel_send_presence (priv->muc);
1108 }
1109
1110 if (!create_dbus_server (tube, error))
1111 return FALSE;
1112
1113 g_signal_emit (G_OBJECT (tube), signals[OFFERED], 0);
1114
1115 return TRUE;
1116 }
1117
1118 static void
message_received(GabbleTubeDBus * tube,TpHandle sender,const char * data,size_t len)1119 message_received (GabbleTubeDBus *tube,
1120 TpHandle sender,
1121 const char *data,
1122 size_t len)
1123 {
1124 GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (tube);
1125 TpBaseChannel *base = TP_BASE_CHANNEL (tube);
1126 TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base);
1127 DBusMessage *msg;
1128 DBusError error = {0,};
1129 const gchar *sender_name;
1130 const gchar *destination;
1131 guint32 serial;
1132
1133 msg = dbus_message_demarshal (data, len, &error);
1134
1135 if (msg == NULL)
1136 {
1137 /* message was corrupted */
1138 DEBUG ("received corrupted message from %d: %s: %s", sender,
1139 error.name, error.message);
1140 dbus_error_free (&error);
1141 return;
1142 }
1143
1144 if (cls->target_handle_type == TP_HANDLE_TYPE_ROOM)
1145 {
1146 destination = dbus_message_get_destination (msg);
1147 /* If destination is NULL this msg is broadcasted (signals) so we don't
1148 * have to check it */
1149 if (destination != NULL && tp_strdiff (priv->dbus_local_name,
1150 destination))
1151 {
1152 /* This message is not intended for this participant.
1153 * Discard it. */
1154 DEBUG ("message not intended for this participant (destination = "
1155 "%s)", destination);
1156 goto unref;
1157 }
1158
1159 sender_name = g_hash_table_lookup (priv->dbus_names,
1160 GUINT_TO_POINTER (sender));
1161
1162 if (tp_strdiff (sender_name, dbus_message_get_sender (msg)))
1163 {
1164 DEBUG ("invalid sender %s (expected %s for sender handle %d)",
1165 dbus_message_get_sender (msg), sender_name, sender);
1166 goto unref;
1167 }
1168 }
1169
1170 if (!priv->dbus_conn)
1171 {
1172 DEBUG ("no D-Bus connection: queuing the message");
1173
1174 /* If the application never connects to the private dbus connection, we
1175 * don't want to eat all the memory. Only queue MAX_QUEUE_SIZE bytes. If
1176 * there are more messages, drop them. */
1177 if (priv->dbus_msg_queue_size + len > MAX_QUEUE_SIZE)
1178 {
1179 DEBUG ("D-Bus message queue size limit reached (%u bytes). "
1180 "Ignore this message.",
1181 MAX_QUEUE_SIZE);
1182 goto unref;
1183 }
1184
1185 priv->dbus_msg_queue = g_slist_prepend (priv->dbus_msg_queue, msg);
1186 priv->dbus_msg_queue_size += len;
1187
1188 /* returns without unref the message */
1189 return;
1190 }
1191
1192 DEBUG ("delivering message from '%s' to '%s'",
1193 dbus_message_get_sender (msg),
1194 dbus_message_get_destination (msg));
1195
1196 /* XXX: what do do if this returns FALSE? */
1197 dbus_connection_send (priv->dbus_conn, msg, &serial);
1198
1199 unref:
1200 dbus_message_unref (msg);
1201 }
1202
1203 static guint32
collect_le32(char * str)1204 collect_le32 (char *str)
1205 {
1206 unsigned char *bytes = (unsigned char *) str;
1207
1208 return bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
1209 }
1210
1211 static guint32
collect_be32(char * str)1212 collect_be32 (char *str)
1213 {
1214 unsigned char *bytes = (unsigned char *) str;
1215
1216 return (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 24) | bytes[3];
1217 }
1218
1219 static void
data_received_cb(GabbleBytestreamIface * stream,TpHandle sender,GString * data,gpointer user_data)1220 data_received_cb (GabbleBytestreamIface *stream,
1221 TpHandle sender,
1222 GString *data,
1223 gpointer user_data)
1224 {
1225 GabbleTubeDBus *tube = GABBLE_TUBE_DBUS (user_data);
1226 GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (tube);
1227 TpBaseChannel *base = TP_BASE_CHANNEL (tube);
1228 TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base);
1229
1230 if (cls->target_handle_type == TP_HANDLE_TYPE_CONTACT)
1231 {
1232 GString *buf = priv->reassembly_buffer;
1233
1234 g_assert (buf != NULL);
1235
1236 g_string_append_len (buf, data->str, data->len);
1237 DEBUG ("Received %" G_GSIZE_FORMAT " bytes, so we now have %"
1238 G_GSIZE_FORMAT " bytes in reassembly buffer", data->len, buf->len);
1239
1240 /* Each D-Bus message has a 16-byte fixed header, in which
1241 *
1242 * * byte 0 is 'l' (ell) or 'B' for endianness
1243 * * bytes 4-7 are body length "n" in bytes in that endianness
1244 * * bytes 12-15 are length "m" of param array in bytes in that
1245 * endianness
1246 *
1247 * followed by m + n + ((8 - (m % 8)) % 8) bytes of other content.
1248 */
1249
1250 while (buf->len >= 16)
1251 {
1252 guint32 body_length, params_length, m;
1253
1254 /* see if we have a whole message and have already calculated
1255 * how many bytes it needs */
1256
1257 if (priv->reassembly_bytes_needed != 0)
1258 {
1259 if (buf->len >= priv->reassembly_bytes_needed)
1260 {
1261 DEBUG ("Received complete D-Bus message of size %"
1262 G_GINT32_FORMAT, priv->reassembly_bytes_needed);
1263 message_received (tube, sender, buf->str,
1264 priv->reassembly_bytes_needed);
1265 g_string_erase (buf, 0, priv->reassembly_bytes_needed);
1266 priv->reassembly_bytes_needed = 0;
1267 }
1268 else
1269 {
1270 /* we'll have to wait for more data */
1271 break;
1272 }
1273 }
1274
1275 if (buf->len < 16)
1276 break;
1277
1278 /* work out how big the next message is going to be */
1279
1280 if (buf->str[0] == DBUS_BIG_ENDIAN)
1281 {
1282 body_length = collect_be32 (buf->str + 4);
1283 m = collect_be32 (buf->str + 12);
1284 }
1285 else if (buf->str[0] == DBUS_LITTLE_ENDIAN)
1286 {
1287 body_length = collect_le32 (buf->str + 4);
1288 m = collect_le32 (buf->str + 12);
1289 }
1290 else
1291 {
1292 DEBUG ("D-Bus message has unknown endianness byte 0x%x, "
1293 "closing tube", (unsigned int) buf->str[0]);
1294 gabble_tube_iface_close ((GabbleTubeIface *) tube, TRUE);
1295 return;
1296 }
1297
1298 /* pad to 8-byte boundary */
1299 params_length = m + ((8 - (m % 8)) % 8);
1300 g_assert (params_length % 8 == 0);
1301 g_assert (params_length >= m);
1302 g_assert (params_length < m + 8);
1303
1304 priv->reassembly_bytes_needed = params_length + body_length + 16;
1305
1306 /* n.b.: this looks as if it could be simplified to just the third
1307 * test, but that would be wrong if the addition had overflowed, so
1308 * don't do that. The first and second tests are sufficient to
1309 * ensure no overflow on 32-bit platforms */
1310 if (body_length > DBUS_MAXIMUM_MESSAGE_LENGTH ||
1311 params_length > DBUS_MAXIMUM_ARRAY_LENGTH ||
1312 priv->reassembly_bytes_needed > DBUS_MAXIMUM_MESSAGE_LENGTH)
1313 {
1314 DEBUG ("D-Bus message is too large to be valid, closing tube");
1315 gabble_tube_iface_close ((GabbleTubeIface *) tube, TRUE);
1316 return;
1317 }
1318
1319 g_assert (priv->reassembly_bytes_needed != 0);
1320 DEBUG ("We need %" G_GINT32_FORMAT " bytes for the next full "
1321 "message", priv->reassembly_bytes_needed);
1322 }
1323 }
1324 else
1325 {
1326 /* MUC bytestreams are message-boundary preserving, which is necessary,
1327 * because we can't assume we started at the beginning */
1328 g_assert (GABBLE_IS_BYTESTREAM_MUC (priv->bytestream));
1329 message_received (tube, sender, data->str, data->len);
1330 }
1331 }
1332
1333 GabbleTubeDBus *
gabble_tube_dbus_new(GabbleConnection * conn,TpHandle handle,TpHandleType handle_type,TpHandle self_handle,TpHandle initiator,const gchar * service,GHashTable * parameters,const gchar * stream_id,guint64 id,GabbleBytestreamIface * bytestream,GabbleMucChannel * muc,gboolean requested)1334 gabble_tube_dbus_new (GabbleConnection *conn,
1335 TpHandle handle,
1336 TpHandleType handle_type,
1337 TpHandle self_handle,
1338 TpHandle initiator,
1339 const gchar *service,
1340 GHashTable *parameters,
1341 const gchar *stream_id,
1342 guint64 id,
1343 GabbleBytestreamIface *bytestream,
1344 GabbleMucChannel *muc,
1345 gboolean requested)
1346 {
1347 GabbleTubeDBus *tube;
1348 GType gtype = GABBLE_TYPE_TUBE_DBUS;
1349
1350 if (handle_type == TP_HANDLE_TYPE_ROOM)
1351 gtype = GABBLE_TYPE_MUC_TUBE_DBUS;
1352
1353 tube = g_object_new (gtype,
1354 "connection", conn,
1355 "handle", handle,
1356 "self-handle", self_handle,
1357 "initiator-handle", initiator,
1358 "service", service,
1359 "parameters", parameters,
1360 "stream-id", stream_id,
1361 "id", id,
1362 "muc", muc,
1363 "requested", requested,
1364 NULL);
1365
1366 if (bytestream != NULL)
1367 g_object_set (tube, "bytestream", bytestream, NULL);
1368
1369 return tube;
1370 }
1371
1372 static void
augment_si_accept_iq(WockyNode * si,gpointer user_data)1373 augment_si_accept_iq (WockyNode *si,
1374 gpointer user_data)
1375 {
1376 wocky_node_add_child_ns (si, "tube", NS_TUBES);
1377 }
1378
1379 /*
1380 * gabble_tube_dbus_accept
1381 *
1382 * Implements gabble_tube_iface_accept on GabbleTubeIface
1383 */
1384 static gboolean
gabble_tube_dbus_accept(GabbleTubeIface * tube,GError ** error)1385 gabble_tube_dbus_accept (GabbleTubeIface *tube,
1386 GError **error)
1387 {
1388 GabbleTubeDBus *self = GABBLE_TUBE_DBUS (tube);
1389 GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self);
1390 TpBaseChannel *base = TP_BASE_CHANNEL (tube);
1391 TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base);
1392 GabbleBytestreamState state;
1393
1394 g_assert (priv->bytestream != NULL);
1395
1396 g_object_get (priv->bytestream,
1397 "state", &state,
1398 NULL);
1399
1400 if (state != GABBLE_BYTESTREAM_STATE_LOCAL_PENDING)
1401 return TRUE;
1402
1403 if (cls->target_handle_type == TP_HANDLE_TYPE_CONTACT)
1404 {
1405 /* Bytestream was created using a SI request so
1406 * we have to accept it */
1407
1408 DEBUG ("accept the SI request");
1409
1410 gabble_bytestream_iface_accept (priv->bytestream, augment_si_accept_iq,
1411 self);
1412 }
1413 else
1414 {
1415 /* No SI so the bytestream is open */
1416 DEBUG ("no SI, bytestream open");
1417 g_object_set (priv->bytestream,
1418 "state", GABBLE_BYTESTREAM_STATE_OPEN,
1419 NULL);
1420 }
1421
1422 if (!create_dbus_server (self, error))
1423 return FALSE;
1424
1425 return TRUE;
1426 }
1427
1428 /*
1429 * gabble_tube_iface_dbus_close
1430 *
1431 * Implements gabble_tube_iface_close on GabbleTubeIface
1432 */
1433 static void
gabble_tube_iface_dbus_close(GabbleTubeIface * tube,gboolean closed_remotely)1434 gabble_tube_iface_dbus_close (GabbleTubeIface *tube,
1435 gboolean closed_remotely)
1436 {
1437 tp_base_channel_close (TP_BASE_CHANNEL (tube));
1438 }
1439
1440 /**
1441 * gabble_tube_dbus_add_bytestream
1442 *
1443 * Implements gabble_tube_iface_add_bytestream on GabbleTubeIface
1444 */
1445 static void
gabble_tube_dbus_add_bytestream(GabbleTubeIface * tube,GabbleBytestreamIface * bytestream)1446 gabble_tube_dbus_add_bytestream (GabbleTubeIface *tube,
1447 GabbleBytestreamIface *bytestream)
1448 {
1449 /* FIXME: should we support this, if we don't have a bytestream yet? */
1450 DEBUG ("D-Bus doesn't support extra bytestream");
1451 gabble_bytestream_iface_close (bytestream, NULL);
1452 }
1453
1454 gboolean
gabble_tube_dbus_add_name(GabbleTubeDBus * self,TpHandle handle,const gchar * name)1455 gabble_tube_dbus_add_name (GabbleTubeDBus *self,
1456 TpHandle handle,
1457 const gchar *name)
1458 {
1459 GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self);
1460 TpBaseChannel *base = TP_BASE_CHANNEL (self);
1461 TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base);
1462 TpBaseConnection *base_conn = tp_base_channel_get_connection (base);
1463 TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
1464 base_conn, TP_HANDLE_TYPE_CONTACT);
1465 gchar *name_copy;
1466 GHashTable *added;
1467 GArray *removed;
1468
1469 g_assert (cls->target_handle_type == TP_HANDLE_TYPE_ROOM);
1470 g_assert (g_hash_table_size (priv->dbus_names) ==
1471 g_hash_table_size (priv->dbus_name_to_handle));
1472
1473 if (g_hash_table_lookup (priv->dbus_names, GUINT_TO_POINTER (handle))
1474 != NULL)
1475 {
1476 DEBUG ("contact %d has already announced his D-Bus name", handle);
1477 return FALSE;
1478 }
1479
1480 if (g_hash_table_lookup (priv->dbus_name_to_handle, name) != NULL)
1481 {
1482 DEBUG ("D-Bus name %s already used", name);
1483 return FALSE;
1484 }
1485
1486 if (g_str_has_prefix (name, ":2."))
1487 {
1488 gchar *nick, *supposed_name;
1489 const gchar *jid;
1490
1491 jid = tp_handle_inspect (contact_repo, handle);
1492 g_assert (wocky_decode_jid (jid, NULL, NULL, &nick));
1493 supposed_name = _gabble_generate_dbus_unique_name (nick);
1494 g_free (nick);
1495
1496 if (tp_strdiff (name, supposed_name))
1497 {
1498 DEBUG ("contact %s announces %s as D-Bus name but it should be %s",
1499 jid, name, supposed_name);
1500 g_free (supposed_name);
1501 return FALSE;
1502 }
1503 g_free (supposed_name);
1504 }
1505
1506 name_copy = g_strdup (name);
1507 g_hash_table_insert (priv->dbus_names, GUINT_TO_POINTER (handle),
1508 name_copy);
1509
1510 g_hash_table_insert (priv->dbus_name_to_handle, name_copy,
1511 GUINT_TO_POINTER (handle));
1512
1513 /* Fire DBusNamesChanged (new API) */
1514 added = g_hash_table_new (g_direct_hash, g_direct_equal);
1515 removed = g_array_new (FALSE, FALSE, sizeof (TpHandle));
1516
1517 g_hash_table_insert (added, GUINT_TO_POINTER (handle), (gchar *) name);
1518
1519 tp_svc_channel_type_dbus_tube_emit_dbus_names_changed (self, added,
1520 removed);
1521
1522 g_hash_table_unref (added);
1523 g_array_unref (removed);
1524
1525 return TRUE;
1526 }
1527
1528 gboolean
gabble_tube_dbus_remove_name(GabbleTubeDBus * self,TpHandle handle)1529 gabble_tube_dbus_remove_name (GabbleTubeDBus *self,
1530 TpHandle handle)
1531 {
1532 GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self);
1533 TpBaseChannel *base = TP_BASE_CHANNEL (self);
1534 TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base);
1535 const gchar *name;
1536 GHashTable *added;
1537 GArray *removed;
1538
1539 g_assert (cls->target_handle_type == TP_HANDLE_TYPE_ROOM);
1540
1541 name = g_hash_table_lookup (priv->dbus_names, GUINT_TO_POINTER (handle));
1542 if (name == NULL)
1543 return FALSE;
1544
1545 g_hash_table_remove (priv->dbus_name_to_handle, name);
1546 g_hash_table_remove (priv->dbus_names, GUINT_TO_POINTER (handle));
1547
1548 g_assert (g_hash_table_size (priv->dbus_names) ==
1549 g_hash_table_size (priv->dbus_name_to_handle));
1550
1551 /* Fire DBusNamesChanged (new API) */
1552 added = g_hash_table_new (g_direct_hash, g_direct_equal);
1553 removed = g_array_new (FALSE, FALSE, sizeof (TpHandle));
1554
1555 g_array_append_val (removed, handle);
1556
1557 tp_svc_channel_type_dbus_tube_emit_dbus_names_changed (self, added,
1558 removed);
1559
1560 g_hash_table_unref (added);
1561 g_array_unref (removed);
1562 return TRUE;
1563 }
1564
1565 gboolean
gabble_tube_dbus_handle_in_names(GabbleTubeDBus * self,TpHandle handle)1566 gabble_tube_dbus_handle_in_names (GabbleTubeDBus *self,
1567 TpHandle handle)
1568 {
1569 GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self);
1570 TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (self);
1571
1572 g_assert (cls->target_handle_type == TP_HANDLE_TYPE_ROOM);
1573
1574 return (g_hash_table_lookup (priv->dbus_names, GUINT_TO_POINTER (handle))
1575 != NULL);
1576 }
1577
1578 gchar *
_gabble_generate_dbus_unique_name(const gchar * nick)1579 _gabble_generate_dbus_unique_name (const gchar *nick)
1580 {
1581 gchar *encoded, *result;
1582 size_t len;
1583 guint i;
1584
1585 len = strlen (nick);
1586
1587 if (len <= 186)
1588 {
1589 encoded = g_base64_encode ((const guchar *) nick, len);
1590 }
1591 else
1592 {
1593 guchar sha1[20];
1594 GString *tmp;
1595
1596 sha1_bin (nick, len, sha1);
1597 tmp = g_string_sized_new (169 + 20);
1598
1599 g_string_append_len (tmp, nick, 169);
1600 g_string_append_len (tmp, (const gchar *) sha1, 20);
1601
1602 encoded = g_base64_encode ((const guchar *) tmp->str, tmp->len);
1603
1604 g_string_free (tmp, TRUE);
1605 }
1606
1607 for (i = 0; encoded[i] != '\0'; i++)
1608 {
1609 switch (encoded[i])
1610 {
1611 case '+':
1612 encoded[i] = '_';
1613 break;
1614 case '/':
1615 encoded[i] = '-';
1616 break;
1617 case '=':
1618 encoded[i] = 'A';
1619 break;
1620 }
1621 }
1622
1623 result = g_strdup_printf (":2.%s", encoded);
1624
1625 g_free (encoded);
1626 return result;
1627 }
1628
1629 const gchar * const *
gabble_tube_dbus_channel_get_allowed_properties(void)1630 gabble_tube_dbus_channel_get_allowed_properties (void)
1631 {
1632 return gabble_tube_dbus_channel_allowed_properties;
1633 }
1634
1635 static gboolean
gabble_tube_dbus_check_access_control(GabbleTubeDBus * self,guint access_control,GError ** error)1636 gabble_tube_dbus_check_access_control (GabbleTubeDBus *self,
1637 guint access_control,
1638 GError **error)
1639 {
1640 switch (access_control)
1641 {
1642 case TP_SOCKET_ACCESS_CONTROL_CREDENTIALS:
1643 case TP_SOCKET_ACCESS_CONTROL_LOCALHOST:
1644 break;
1645
1646 default:
1647 g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
1648 "%u socket access control is not supported", access_control);
1649 return FALSE;
1650 }
1651
1652 return TRUE;
1653 }
1654
1655 /**
1656 * gabble_tube_dbus_offer_async
1657 *
1658 * Implemnets D-Bus method Offer on interface
1659 * org.freedesktop.Telepathy.Channel.Type.DBusTube
1660 */
1661 static void
gabble_tube_dbus_offer_async(TpSvcChannelTypeDBusTube * self,GHashTable * parameters,guint access_control,DBusGMethodInvocation * context)1662 gabble_tube_dbus_offer_async (TpSvcChannelTypeDBusTube *self,
1663 GHashTable *parameters,
1664 guint access_control,
1665 DBusGMethodInvocation *context)
1666 {
1667 GabbleTubeDBus *tube = GABBLE_TUBE_DBUS (self);
1668 GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (tube);
1669 GError *error = NULL;
1670
1671 if (!gabble_tube_dbus_check_access_control (tube, access_control, &error))
1672 {
1673 dbus_g_method_return_error (context, error);
1674 g_error_free (error);
1675 return;
1676 }
1677
1678 priv->access_control = access_control;
1679
1680 g_object_set (self, "parameters", parameters, NULL);
1681
1682 if (gabble_tube_dbus_offer (tube, &error))
1683 {
1684 tp_svc_channel_type_dbus_tube_return_from_offer (context,
1685 tube->priv->dbus_srv_addr);
1686 }
1687 else
1688 {
1689 g_assert (error != NULL);
1690 dbus_g_method_return_error (context, error);
1691 g_error_free (error);
1692 }
1693 }
1694
1695 /**
1696 * gabble_tube_dbus_accept_async
1697 *
1698 * Implements D-Bus method Accept on interface
1699 * org.freedesktop.Telepathy.Channel.Type.DBusTube
1700 */
1701 static void
gabble_tube_dbus_accept_async(TpSvcChannelTypeDBusTube * self,guint access_control,DBusGMethodInvocation * context)1702 gabble_tube_dbus_accept_async (TpSvcChannelTypeDBusTube *self,
1703 guint access_control,
1704 DBusGMethodInvocation *context)
1705 {
1706 GabbleTubeDBus *tube = GABBLE_TUBE_DBUS (self);
1707 GError *error = NULL;
1708
1709 if (!gabble_tube_dbus_check_access_control (tube, access_control, &error))
1710 {
1711 dbus_g_method_return_error (context, error);
1712 g_error_free (error);
1713 return;
1714 }
1715
1716 if (gabble_tube_dbus_accept (GABBLE_TUBE_IFACE (tube), &error))
1717 {
1718 tp_svc_channel_type_dbus_tube_return_from_accept (context,
1719 tube->priv->dbus_srv_addr);
1720 ;
1721 }
1722 else
1723 {
1724 g_assert (error != NULL);
1725 dbus_g_method_return_error (context, error);
1726 g_error_free (error);
1727 }
1728 }
1729
1730 static void
tube_iface_init(gpointer g_iface,gpointer iface_data)1731 tube_iface_init (gpointer g_iface,
1732 gpointer iface_data)
1733 {
1734 GabbleTubeIfaceClass *klass = (GabbleTubeIfaceClass *) g_iface;
1735
1736 klass->accept = gabble_tube_dbus_accept;
1737 klass->close = gabble_tube_iface_dbus_close;
1738 klass->add_bytestream = gabble_tube_dbus_add_bytestream;
1739 }
1740
1741 static void
dbustube_iface_init(gpointer g_iface,gpointer iface_data)1742 dbustube_iface_init (gpointer g_iface,
1743 gpointer iface_data)
1744 {
1745 TpSvcChannelTypeDBusTubeClass *klass =
1746 (TpSvcChannelTypeDBusTubeClass *) g_iface;
1747
1748 #define IMPLEMENT(x, suffix) tp_svc_channel_type_dbus_tube_implement_##x (\
1749 klass, gabble_tube_dbus_##x##suffix)
1750 IMPLEMENT(offer,_async);
1751 IMPLEMENT(accept,_async);
1752 #undef IMPLEMENT
1753 }
1754