107
107
#define SALUT_TUBES_CHANNEL_GET_PRIVATE(obj) \
108
((SalutTubesChannelPrivate *) obj->priv)
108
((SalutTubesChannelPrivate *) ((SalutTubesChannel *)obj)->priv)
110
static gboolean update_tubes_info (SalutTubesChannel *self, gboolean request);
111
static void muc_connection_received_stanza_cb (GibberMucConnection *conn,
112
const gchar *sender, GibberXmppStanza *stanza, gpointer user_data);
113
static void muc_connection_lost_sender_cb (GibberMucConnection *conn,
114
const gchar *sender, gpointer user_data);
110
static gboolean update_tubes_info (SalutTubesChannel *self);
111
static void muc_connection_lost_senders_cb (GibberMucConnection *conn,
112
GArray *senders, gpointer user_data);
113
static void muc_connection_new_senders_cb (GibberMucConnection *conn,
114
GArray *senders, gpointer user_data);
115
115
static gboolean extract_tube_information (SalutTubesChannel *self,
116
GibberXmppNode *tube_node, SalutTubeType *type, TpHandle *initiator_handle,
117
const gchar **service, GHashTable **parameters, gboolean *offering,
120
create_new_tube (SalutTubesChannel *self, SalutTubeType type, TpHandle initiator,
121
const gchar *service, GHashTable *parameters, const gchar *stream_id,
116
GibberXmppNode *tube_node, TpTubeType *type, TpHandle *initiator_handle,
117
const gchar **service, GHashTable **parameters, guint *tube_id);
118
static SalutTubeIface * create_new_tube (SalutTubesChannel *self,
119
TpTubeType type, TpHandle initiator, const gchar *service,
120
GHashTable *parameters, guint tube_id, GibberBytestreamIface *bytestream);
125
123
salut_tubes_channel_init (SalutTubesChannel *self)
369
374
* on org.freedesktop.Telepathy.Channel.Type.Tubes
372
salut_tubes_channel_get_available_tube_types (SalutSvcChannelTypeTubes *iface,
377
salut_tubes_channel_get_available_tube_types (TpSvcChannelTypeTubes *iface,
373
378
DBusGMethodInvocation *context)
375
380
SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
379
384
g_assert (SALUT_IS_TUBES_CHANNEL (self));
381
ret = g_array_sized_new (FALSE, FALSE, sizeof (SalutTubeType), 1);
382
type = SALUT_TUBE_TYPE_DBUS;
383
g_array_append_val (ret, type);
385
type = TP_TUBE_TYPE_STREAM_UNIX;
386
g_array_append_val (ret, type);
386
ret = g_array_sized_new (FALSE, FALSE, sizeof (TpTubeType), 1);
387
type = TP_TUBE_TYPE_DBUS;
388
g_array_append_val (ret, type);
389
type = TP_TUBE_TYPE_STREAM;
390
g_array_append_val (ret, type);
389
salut_svc_channel_type_tubes_return_from_get_available_tube_types (context,
392
tp_svc_channel_type_tubes_return_from_get_available_tube_types (context,
392
395
g_array_free (ret, TRUE);
395
#ifdef HAVE_DBUS_TUBE
396
398
struct _add_in_old_dbus_tubes_data
398
400
GHashTable *old_dbus_tubes;
445
442
SalutTubeDBus *tube = SALUT_TUBE_DBUS (value);
446
443
struct _emit_d_bus_names_changed_foreach_data *data =
447
444
(struct _emit_d_bus_names_changed_foreach_data *) user_data;
449
445
SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (
451
TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
452
(TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
454
/* Remove from the D-Bus names mapping */
455
g_object_get (tube, "dbus-names", &names, NULL);
456
g_hash_table_remove (names, GUINT_TO_POINTER (data->contact));
457
g_hash_table_unref (names);
459
/* Emit the DBusNamesChanged signal */
460
d_bus_names_changed_removed (data->self, tube_id, data->contact);
462
tp_handle_unref (contact_repo, data->contact);
448
if (salut_tube_dbus_remove_name (tube, data->contact))
450
/* Emit the DBusNamesChanged signal */
451
d_bus_names_changed_removed (data->self, tube_id, data->contact);
454
/* Remove the contact as sender in the muc bytestream */
455
if (priv->handle_type == TP_HANDLE_TYPE_ROOM)
457
GibberBytestreamIface *bytestream;
459
g_object_get (tube, "bytestream", &bytestream, NULL);
460
g_assert (bytestream != NULL);
462
if (GIBBER_IS_BYTESTREAM_MUC (bytestream))
464
TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
465
(TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
468
sender = tp_handle_inspect (contact_repo, data->contact);
470
gibber_bytestream_muc_remove_sender (
471
GIBBER_BYTESTREAM_MUC (bytestream), sender);
474
g_object_unref (bytestream);
467
muc_connection_received_stanza_cb (GibberMucConnection *conn,
469
GibberXmppStanza *stanza,
479
tubes_message_received (SalutTubesChannel *self,
481
GibberXmppStanza *stanza)
472
SalutTubesChannel *self = SALUT_TUBES_CHANNEL (user_data);
473
483
SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
474
484
TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
475
485
(TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
476
486
TpHandle contact;
477
487
GibberXmppNode *tubes_node;
479
gboolean request = FALSE;
480
#ifdef HAVE_DBUS_TUBE
481
489
GHashTable *old_dbus_tubes;
482
490
struct _add_in_old_dbus_tubes_data add_data;
483
491
struct _emit_d_bus_names_changed_foreach_data emit_data;
492
GibberStanzaType type;
493
GibberStanzaSubType sub_type;
486
495
contact = tp_handle_lookup (contact_repo, sender, NULL, NULL);
489
DEBUG ("unknown sender: %s", sender);
496
g_assert (contact != 0);
493
498
if (contact == priv->self_handle)
494
/* We don't need to inspect our own presence */
499
/* We don't need to inspect our own tubes */
502
gibber_xmpp_stanza_get_type_info (stanza, &type, &sub_type);
503
if (type != GIBBER_STANZA_TYPE_MESSAGE
504
|| sub_type != GIBBER_STANZA_SUB_TYPE_GROUPCHAT)
497
507
tubes_node = gibber_xmpp_node_get_child_ns (stanza->node, "tubes",
498
508
GIBBER_TELEPATHY_NS_TUBES);
499
if (tubes_node == NULL)
502
if (!tp_strdiff (gibber_xmpp_node_get_attribute (tubes_node, "request"),
506
#ifdef HAVE_DBUS_TUBE
509
g_assert (tubes_node != NULL);
507
511
/* Fill old_dbus_tubes with D-BUS tubes previoulsy announced by
509
513
old_dbus_tubes = g_hash_table_new (g_direct_hash, g_direct_equal);
510
514
add_data.old_dbus_tubes = old_dbus_tubes;
511
515
add_data.contact = contact;
512
516
g_hash_table_foreach (priv->tubes, add_in_old_dbus_tubes, &add_data);
515
518
for (l = tubes_node->children; l != NULL; l = l->next)
518
521
const gchar *stream_id;
519
522
SalutTubeIface *tube;
523
526
stream_id = gibber_xmpp_node_get_attribute (tube_node, "stream-id");
524
if (stream_id == NULL)
526
DEBUG ("no stream id attribute");
530
528
extract_tube_information (self, tube_node, NULL,
531
NULL, NULL, NULL, NULL, &tube_id);
529
NULL, NULL, NULL, &tube_id);
532
530
tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
534
532
if (tube == NULL)
536
534
/* We don't know yet this tube */
537
535
const gchar *service;
539
537
TpHandle initiator_handle;
540
538
GHashTable *parameters;
543
541
if (extract_tube_information (self, tube_node, &type,
544
&initiator_handle, &service, ¶meters, NULL, &tube_id))
542
&initiator_handle, &service, ¶meters, &tube_id))
547
#ifndef HAVE_DBUS_TUBE
548
if (type == SALUT_TUBE_TYPE_DBUS)
550
DEBUG ("Don't create the tube as D-Bus tube support"
546
case TP_TUBE_TYPE_DBUS:
548
if (initiator_handle == 0)
550
DEBUG ("D-Bus tube initiator missing");
551
/* skip to the next child of <tubes> */
556
case TP_TUBE_TYPE_STREAM:
558
if (initiator_handle != 0)
560
tp_handle_unref (contact_repo, initiator_handle);
562
initiator_handle = contact;
563
tp_handle_ref (contact_repo, initiator_handle);
568
g_assert_not_reached ();
556
create_new_tube (self, type, initiator_handle,
557
service, parameters, stream_id, tube_id);
558
tube = g_hash_table_lookup (priv->tubes,
559
GUINT_TO_POINTER (tube_id));
572
tube = create_new_tube (self, type, initiator_handle,
573
service, parameters, tube_id, NULL);
561
575
/* the tube has reffed its initiator, no need to keep a ref */
562
576
tp_handle_unref (contact_repo, initiator_handle);
565
#ifdef HAVE_DBUS_TUBE
568
581
/* The contact is in the tube.
569
582
* Remove it from old_dbus_tubes if needed */
570
583
g_hash_table_remove (old_dbus_tubes, GUINT_TO_POINTER (tube_id));
574
586
if (tube == NULL)
577
589
g_object_get (tube, "type", &type, NULL);
579
#ifdef HAVE_DBUS_TUBE
580
if (type == SALUT_TUBE_TYPE_DBUS)
591
if (type == TP_TUBE_TYPE_DBUS)
582
593
/* Update mapping of handle -> D-Bus name. */
587
g_object_get (tube, "dbus-names", &names, NULL);
589
name = g_hash_table_lookup (names, GUINT_TO_POINTER (contact));
594
if (!salut_tube_dbus_handle_in_names (SALUT_TUBE_DBUS (tube),
593
597
/* Contact just joined the tube */
594
598
const gchar *new_name;
621
640
g_hash_table_destroy (old_dbus_tubes);
625
/* Contact requested tubes information */
626
update_tubes_info (self, FALSE);
630
muc_connection_lost_sender_cb (GibberMucConnection *conn,
644
muc_connection_new_senders_cb (GibberMucConnection *conn,
632
646
gpointer user_data)
634
648
SalutTubesChannel *self = SALUT_TUBES_CHANNEL (user_data);
650
update_tubes_info (self);
654
muc_connection_lost_senders_cb (GibberMucConnection *conn,
658
SalutTubesChannel *self = SALUT_TUBES_CHANNEL (user_data);
635
659
SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
636
660
TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
637
661
(TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
639
GHashTable *old_dbus_tubes;
640
struct _add_in_old_dbus_tubes_data add_data;
641
struct _emit_d_bus_names_changed_foreach_data emit_data;
643
contact = tp_handle_lookup (contact_repo, sender, NULL, NULL);
664
for (i = 0; i < senders->len; i++)
646
DEBUG ("unknown sender: %s", sender);
668
GHashTable *old_dbus_tubes;
669
struct _add_in_old_dbus_tubes_data add_data;
670
struct _emit_d_bus_names_changed_foreach_data emit_data;
672
sender = g_array_index (senders, gchar *, i);
674
contact = tp_handle_lookup (contact_repo, sender, NULL, NULL);
677
DEBUG ("unknown sender: %s", sender);
681
old_dbus_tubes = g_hash_table_new (g_direct_hash, g_direct_equal);
682
add_data.old_dbus_tubes = old_dbus_tubes;
683
add_data.contact = contact;
684
g_hash_table_foreach (priv->tubes, add_in_old_dbus_tubes, &add_data);
686
/* contact left the muc so he left all its tubes */
687
emit_data.contact = contact;
688
emit_data.self = self;
689
g_hash_table_foreach (old_dbus_tubes, emit_d_bus_names_changed_foreach,
692
g_hash_table_destroy (old_dbus_tubes);
650
old_dbus_tubes = g_hash_table_new (g_direct_hash, g_direct_equal);
651
add_data.old_dbus_tubes = old_dbus_tubes;
652
add_data.contact = contact;
653
g_hash_table_foreach (priv->tubes, add_in_old_dbus_tubes, &add_data);
655
/* contact left the muc so he left all its tubes */
656
emit_data.contact = contact;
657
emit_data.self = self;
658
g_hash_table_foreach (old_dbus_tubes, emit_d_bus_names_changed_foreach,
661
g_hash_table_destroy (old_dbus_tubes);
805
#ifdef HAVE_DBUS_TUBE
806
case SALUT_TUBE_TYPE_DBUS:
835
case TP_TUBE_TYPE_DBUS:
807
836
tube = SALUT_TUBE_IFACE (salut_tube_dbus_new (priv->conn,
808
837
priv->handle, priv->handle_type, priv->self_handle, muc_connection,
809
initiator, service, parameters, stream_id, tube_id));
838
initiator, service, parameters, tube_id, bytestream));
813
case TP_TUBE_TYPE_STREAM_UNIX:
840
case TP_TUBE_TYPE_STREAM:
814
841
tube = SALUT_TUBE_IFACE (salut_tube_stream_new (priv->conn,
815
842
priv->handle, priv->handle_type, priv->self_handle, initiator,
816
843
service, parameters, tube_id));
820
846
g_assert_not_reached ();
823
849
DEBUG ("create tube %u", tube_id);
824
850
g_hash_table_insert (priv->tubes, GUINT_TO_POINTER (tube_id), tube);
825
update_tubes_info (self, FALSE);
851
update_tubes_info (self);
827
853
g_object_get (tube, "state", &state, NULL);
829
salut_svc_channel_type_tubes_emit_new_tube (self,
855
tp_svc_channel_type_tubes_emit_new_tube (self,
977
997
SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
978
998
GibberXmppNode *parameters_node;
979
999
GHashTable *parameters;
981
1001
gchar *service, *id_str;
983
1003
TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
984
1004
(TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
985
1005
TpHandle initiator_handle;
986
const gchar *initiator;
988
1007
g_object_get (G_OBJECT (tube),
1009
"initiator", &initiator_handle,
989
1010
"service", &service,
990
1011
"parameters", ¶meters,
993
"initiator", &initiator_handle,
996
1015
id_str = g_strdup_printf ("%u", tube_id);
998
1017
gibber_xmpp_node_set_attribute (node, "service", service);
999
1018
gibber_xmpp_node_set_attribute (node, "id", id_str);
1000
initiator = tp_handle_inspect (contact_repo, initiator_handle);
1001
gibber_xmpp_node_set_attribute (node, "initiator", initiator);
1003
1020
g_free (id_str);
1007
case SALUT_TUBE_TYPE_DBUS:
1008
gibber_xmpp_node_set_attribute (node, "type", "dbus");
1024
case TP_TUBE_TYPE_DBUS:
1026
gchar *name, *stream_id;
1028
g_object_get (G_OBJECT (tube),
1030
"stream-id", &stream_id,
1033
gibber_xmpp_node_set_attribute (node, "type", "dbus");
1034
gibber_xmpp_node_set_attribute (node, "stream-id", stream_id);
1035
gibber_xmpp_node_set_attribute (node, "initiator",
1036
tp_handle_inspect (contact_repo, initiator_handle));
1039
gibber_xmpp_node_set_attribute (node, "dbus-name", name);
1011
case TP_TUBE_TYPE_STREAM_UNIX:
1046
case TP_TUBE_TYPE_STREAM:
1012
1047
gibber_xmpp_node_set_attribute (node, "type", "stream");
1016
1050
g_assert_not_reached ();
1019
if (type == SALUT_TUBE_TYPE_DBUS)
1021
gchar *name, *stream_id;
1023
g_object_get (G_OBJECT (tube),
1025
"stream-id", &stream_id,
1028
gibber_xmpp_node_set_attribute (node, "dbus-name", name);
1029
gibber_xmpp_node_set_attribute (node, "stream-id", stream_id);
1035
1053
parameters_node = gibber_xmpp_node_add_child (node, "parameters");
1036
1054
salut_gibber_xmpp_node_add_children_from_properties (parameters_node,
1037
1055
parameters, "parameter");
1148
1160
* on org.freedesktop.Telepathy.Channel.Type.Tubes
1151
salut_tubes_channel_offer_tube (SalutSvcChannelTypeTubes *iface,
1153
const gchar *service,
1154
GHashTable *parameters,
1155
DBusGMethodInvocation *context)
1157
#ifdef HAVE_DBUS_TUBE
1158
SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
1159
SalutTubesChannelPrivate *priv;
1160
TpBaseConnection *base;
1162
SalutTubeIface *tube;
1163
GHashTable *parameters_copied;
1166
g_assert (SALUT_IS_TUBES_CHANNEL (self));
1168
priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
1169
base = (TpBaseConnection*) priv->conn;
1171
if (type != SALUT_TUBE_TYPE_DBUS)
1173
GError *error = g_error_new (TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
1174
"invalid type: %d", type);
1176
dbus_g_method_return_error (context, error);
1177
g_error_free (error);
1182
parameters_copied = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
1183
(GDestroyNotify) tp_g_value_slice_free);
1184
g_hash_table_foreach (parameters, copy_parameter, parameters_copied);
1186
stream_id = generate_stream_id ();
1187
tube_id = generate_tube_id ();
1189
create_new_tube (self, SALUT_TUBE_TYPE_DBUS, priv->self_handle,
1190
service, parameters_copied, (const gchar*) stream_id, tube_id);
1192
tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
1194
salut_svc_channel_type_tubes_return_from_offer_tube (context, tube_id);
1198
GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
1199
"D-Bus tube support not built" };
1201
dbus_g_method_return_error (context, &error);
1207
* salut_tubes_channel_offer_stream_unix_tube
1209
* Implements D-Bus method OfferStreamUnixTube
1210
* on org.freedesktop.Telepathy.Channel.Type.Tubes
1214
salut_tubes_channel_offer_stream_unix_tube (SalutSvcChannelTypeTubes *iface,
1215
const gchar *service,
1216
const gchar *socket,
1217
GHashTable *parameters,
1218
DBusGMethodInvocation *context)
1220
GError error = { TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
1221
"Stream Unix tube not implemented" };
1223
dbus_g_method_return_error (context, &error);
1225
SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
1226
SalutTubesChannelPrivate *priv;
1227
TpBaseConnection *base;
1229
SalutTubeIface *tube;
1230
GHashTable *parameters_copied;
1232
struct stat stat_buff;
1234
g_assert (SALUT_IS_TUBES_CHANNEL (self));
1236
priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
1237
base = (TpBaseConnection*) priv->conn;
1239
if (g_stat (socket, &stat_buff) == -1)
1241
GError *error = NULL;
1243
DEBUG ("Error calling stat on socket: %s", g_strerror (errno));
1245
error = g_error_new (TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, "%s: %s",
1246
socket, g_strerror (errno));
1248
dbus_g_method_return_error (context, error);
1250
g_error_free (error);
1254
if (!S_ISSOCK (stat_buff.st_mode))
1256
GError *error = NULL;
1258
DEBUG ("%s is not a socket", socket);
1260
error = g_error_new (TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
1261
"%s is not a socket", socket);
1263
dbus_g_method_return_error (context, error);
1265
g_error_free (error);
1269
parameters_copied = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
1270
(GDestroyNotify) tp_g_value_slice_free);
1271
g_hash_table_foreach (parameters, copy_parameter, parameters_copied);
1273
stream_id = salut_bytestream_factory_generate_stream_id ();
1274
tube_id = generate_tube_id ();
1276
create_new_tube (self, TP_TUBE_TYPE_STREAM_UNIX, priv->self_handle,
1277
service, parameters_copied, (const gchar*) stream_id, tube_id);
1279
tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
1281
g_object_set (tube, "socket", socket, NULL);
1283
if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
1285
/* Stream initiation */
1286
GError *error = NULL;
1288
if (!start_stream_initiation (self, tube, stream_id, &error))
1290
salut_tube_iface_close (tube);
1292
dbus_g_method_return_error (context, error);
1294
g_error_free (error);
1300
g_signal_connect (tube, "new-connection",
1301
G_CALLBACK (stream_unix_tube_new_connection_cb), self);
1163
salut_tubes_channel_offer_d_bus_tube (TpSvcChannelTypeTubes *iface,
1164
const gchar *service,
1165
GHashTable *parameters,
1166
DBusGMethodInvocation *context)
1168
SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
1169
SalutTubesChannelPrivate *priv;
1170
TpBaseConnection *base;
1172
SalutTubeIface *tube;
1173
GHashTable *parameters_copied;
1175
g_assert (SALUT_IS_TUBES_CHANNEL (self));
1177
priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
1178
base = (TpBaseConnection*) priv->conn;
1180
if (priv->handle_type == TP_HANDLE_TYPE_ROOM
1181
&& !tp_handle_set_is_member (TP_GROUP_MIXIN(self->muc)->members,
1184
GError error = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
1185
"Tube channel isn't connected" };
1187
dbus_g_method_return_error (context, &error);
1191
parameters_copied = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
1192
(GDestroyNotify) tp_g_value_slice_free);
1193
g_hash_table_foreach (parameters, copy_parameter, parameters_copied);
1195
tube_id = generate_tube_id ();
1197
tube = create_new_tube (self, TP_TUBE_TYPE_DBUS, priv->self_handle,
1198
service, parameters_copied, tube_id, NULL);
1303
1200
tp_svc_channel_type_tubes_return_from_offer_d_bus_tube (context, tube_id);
1310
* salut_tubes_channel_accept_tube
1204
* salut_tubes_channel_accept_d_bus_tube
1312
* Implements D-Bus method AcceptTube
1206
* Implements D-Bus method AcceptDBusTube
1313
1207
* on org.freedesktop.Telepathy.Channel.Type.Tubes
1316
salut_tubes_channel_accept_tube (SalutSvcChannelTypeTubes *iface,
1318
DBusGMethodInvocation *context)
1210
salut_tubes_channel_accept_d_bus_tube (TpSvcChannelTypeTubes *iface,
1212
DBusGMethodInvocation *context)
1320
1214
SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
1321
1215
SalutTubesChannelPrivate *priv;
1322
1216
SalutTubeIface *tube;
1323
SalutTubeState state;
1326
1221
g_assert (SALUT_IS_TUBES_CHANNEL (self));
1340
g_object_get (tube, "state", &state, NULL);
1341
if (state != SALUT_TUBE_STATE_LOCAL_PENDING)
1343
/* XXX raise an error if the tube was not in the local pending state ? */
1344
salut_svc_channel_type_tubes_return_from_accept_tube (context);
1348
salut_tube_iface_accept (tube);
1350
update_tubes_info (self, FALSE);
1352
g_object_get (tube, "type", &type, NULL);
1354
#ifdef HAVE_DBUS_TUBE
1355
if (type == SALUT_TUBE_TYPE_DBUS)
1357
add_yourself_in_dbus_names (self, id);
1361
salut_svc_channel_type_tubes_return_from_accept_tube (context);
1240
if (type != TP_TUBE_TYPE_DBUS)
1242
GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
1243
"Tube is not a D-Bus tube" };
1245
dbus_g_method_return_error (context, &error);
1249
if (state != TP_TUBE_STATE_LOCAL_PENDING)
1251
GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
1252
"Tube is not in the local pending state" };
1254
dbus_g_method_return_error (context, &error);
1259
salut_tube_iface_accept (tube, NULL);
1261
update_tubes_info (self);
1264
"dbus-address", &addr,
1267
add_yourself_in_dbus_names (self, id);
1269
tp_svc_channel_type_tubes_return_from_accept_d_bus_tube (context, addr);
1546
1443
ret = g_ptr_array_sized_new (g_hash_table_size (names));
1547
1444
g_hash_table_foreach (names, get_d_bus_names_foreach, ret);
1549
salut_svc_channel_type_tubes_return_from_get_d_bus_names (context, ret);
1446
tp_svc_channel_type_tubes_return_from_get_d_bus_names (context, ret);
1551
1448
for (i = 0; i < ret->len; i++)
1552
1449
g_boxed_free (DBUS_NAME_PAIR_TYPE, ret->pdata[i]);
1553
1450
g_hash_table_unref (names);
1554
1451
g_ptr_array_free (ret, TRUE);
1556
#else /* HAVE_DBUS_TUBE */
1558
GError error = { TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
1559
"D-Bus tube support not built" };
1561
dbus_g_method_return_error (context, &error);
1566
* salut_tubes_channel_get_stream_unix_socket_address
1568
* Implements D-Bus method GetStreamSocketAddress
1569
* on org.freedesktop.Telepathy.Channel.Type.Tubes
1573
salut_tubes_channel_get_stream_unix_socket_address (SalutSvcChannelTypeTubes *iface,
1455
stream_tube_new_connection_cb (SalutTubeIface *tube,
1459
SalutTubesChannel *self = SALUT_TUBES_CHANNEL (user_data);
1468
g_assert (type == TP_TUBE_TYPE_STREAM);
1470
tp_svc_channel_type_tubes_emit_stream_tube_new_connection (self,
1475
* salut_tubes_channel_offer_stream_tube
1477
* Implements D-Bus method OfferStreamTube
1478
* on org.freedesktop.Telepathy.Channel.Type.Tubes
1481
salut_tubes_channel_offer_stream_tube (TpSvcChannelTypeTubes *iface,
1482
const gchar *service,
1483
GHashTable *parameters,
1485
const GValue *address,
1486
guint access_control,
1487
const GValue *access_control_param,
1488
DBusGMethodInvocation *context)
1490
SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
1491
SalutTubesChannelPrivate *priv;
1492
TpBaseConnection *base;
1494
SalutTubeIface *tube;
1495
GHashTable *parameters_copied;
1496
GError *error = NULL;
1498
priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
1499
base = (TpBaseConnection*) priv->conn;
1501
if (priv->handle_type == TP_HANDLE_TYPE_ROOM
1502
&& !tp_handle_set_is_member (TP_GROUP_MIXIN(self->muc)->members,
1505
GError error = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
1506
"Tube channel isn't connected" };
1508
dbus_g_method_return_error (context, &error);
1512
if (!salut_tube_stream_check_params (address_type, address,
1513
access_control, access_control_param, &error))
1515
dbus_g_method_return_error (context, error);
1516
g_error_free (error);
1520
parameters_copied = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
1521
(GDestroyNotify) tp_g_value_slice_free);
1522
g_hash_table_foreach (parameters, copy_parameter, parameters_copied);
1524
tube_id = generate_tube_id ();
1526
tube = create_new_tube (self, TP_TUBE_TYPE_STREAM, priv->self_handle,
1527
service, parameters_copied, tube_id, NULL);
1530
"address-type", address_type,
1532
"access-control", access_control,
1533
"access-control-param", access_control_param,
1536
g_signal_connect (tube, "new-connection",
1537
G_CALLBACK (stream_tube_new_connection_cb), self);
1539
tp_svc_channel_type_tubes_return_from_offer_stream_tube (context,
1544
* salut_tubes_channel_accept_stream_tube
1546
* Implements D-Bus method AcceptStreamTube
1547
* on org.freedesktop.Telepathy.Channel.Type.Tubes
1550
salut_tubes_channel_accept_stream_tube (TpSvcChannelTypeTubes *iface,
1553
guint access_control,
1554
const GValue *access_control_param,
1555
DBusGMethodInvocation *context)
1557
SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
1558
SalutTubesChannelPrivate *priv;
1559
SalutTubeIface *tube;
1563
GError *error = NULL;
1565
g_assert (SALUT_IS_TUBES_CHANNEL (self));
1567
priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
1569
tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (id));
1572
GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, "Unknown tube" };
1574
dbus_g_method_return_error (context, &error);
1578
if (address_type != TP_SOCKET_ADDRESS_TYPE_UNIX &&
1579
address_type != TP_SOCKET_ADDRESS_TYPE_IPV4 &&
1580
address_type != TP_SOCKET_ADDRESS_TYPE_IPV6)
1582
GError *error = NULL;
1584
error = g_error_new (TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
1585
"Address type %d not implemented", address_type);
1587
dbus_g_method_return_error (context, error);
1589
g_error_free (error);
1593
if (access_control != TP_SOCKET_ACCESS_CONTROL_LOCALHOST)
1595
GError *error = NULL;
1597
error = g_error_new (TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
1598
"Unix sockets only support localhost control access");
1600
dbus_g_method_return_error (context, error);
1602
g_error_free (error);
1611
if (type != TP_TUBE_TYPE_STREAM)
1613
GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
1614
"Tube is not a stream tube" };
1616
dbus_g_method_return_error (context, &error);
1620
if (state != TP_TUBE_STATE_LOCAL_PENDING)
1622
GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
1623
"Tube is not in the local pending state" };
1625
dbus_g_method_return_error (context, &error);
1630
"address-type", address_type,
1631
"access-control", access_control,
1632
"access-control-param", access_control_param,
1635
if (!salut_tube_iface_accept (tube, &error))
1637
dbus_g_method_return_error (context, error);
1641
update_tubes_info (self);
1643
g_object_get (tube, "address", &address, NULL);
1645
tp_svc_channel_type_tubes_return_from_accept_stream_tube (context,
1650
* salut_tubes_channel_get_stream_tube_socket_address
1652
* Implements D-Bus method GetStreamTubeSocketAddress
1653
* on org.freedesktop.Telepathy.Channel.Type.Tubes
1656
salut_tubes_channel_get_stream_tube_socket_address (TpSvcChannelTypeTubes *iface,
1575
1658
DBusGMethodInvocation *context)
1577
1660
SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
1578
1661
SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
1579
1662
SalutTubeIface *tube;
1581
SalutTubeState state;
1666
TpSocketAddressType address_type;
1584
1668
tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (id));
1585
1669
if (tube == NULL)
1616
1700
g_object_get (tube,
1701
"address", &address,
1702
"address-type", &address_type,
1620
tp_svc_channel_type_tubes_return_from_get_stream_unix_socket_address (
1705
tp_svc_channel_type_tubes_return_from_get_stream_tube_socket_address (
1706
context, address_type, address);
1710
* salut_tubes_channel_get_available_stream_tube_types
1712
* Implements D-Bus method GetAvailableStreamTubeTypes
1713
* on org.freedesktop.Telepathy.Channel.Type.Tubes
1716
salut_tubes_channel_get_available_stream_tube_types (
1717
TpSvcChannelTypeTubes *iface,
1718
DBusGMethodInvocation *context)
1721
GArray *unix_tab, *ipv4_tab, *ipv6_tab;
1722
TpSocketAccessControl access;
1724
ret = g_hash_table_new (g_direct_hash, g_direct_equal);
1726
/* Socket_Address_Type_Unix */
1727
unix_tab = g_array_sized_new (FALSE, FALSE, sizeof (TpSocketAccessControl),
1729
access = TP_SOCKET_ACCESS_CONTROL_LOCALHOST;
1730
g_array_append_val (unix_tab, access);
1731
g_hash_table_insert (ret, GUINT_TO_POINTER (TP_SOCKET_ADDRESS_TYPE_UNIX),
1734
/* Socket_Address_Type_IPv4 */
1735
ipv4_tab = g_array_sized_new (FALSE, FALSE, sizeof (TpSocketAccessControl),
1737
access = TP_SOCKET_ACCESS_CONTROL_LOCALHOST;
1738
g_array_append_val (ipv4_tab, access);
1739
g_hash_table_insert (ret, GUINT_TO_POINTER (TP_SOCKET_ADDRESS_TYPE_IPV4),
1742
/* Socket_Address_Type_IPv6 */
1743
ipv6_tab = g_array_sized_new (FALSE, FALSE, sizeof (TpSocketAccessControl),
1745
access = TP_SOCKET_ACCESS_CONTROL_LOCALHOST;
1746
g_array_append_val (ipv6_tab, access);
1747
g_hash_table_insert (ret, GUINT_TO_POINTER (TP_SOCKET_ADDRESS_TYPE_IPV6),
1750
tp_svc_channel_type_tubes_return_from_get_available_stream_tube_types (
1753
g_array_free (unix_tab, TRUE);
1754
g_array_free (ipv4_tab, TRUE);
1755
g_array_free (ipv6_tab, TRUE);
1756
g_hash_table_destroy (ret);
1627
1759
static void salut_tubes_channel_dispose (GObject *object);
1628
1760
static void salut_tubes_channel_finalize (GObject *object);
1974
/* Called when we receive a SI request,
1975
* via either salut_muc_manager_handle_si_stream_request or
1976
* salut_tubes_manager_handle_si_stream_request
1979
salut_tubes_channel_bytestream_offered (SalutTubesChannel *self,
1980
GibberBytestreamIface *bytestream,
1981
GibberXmppStanza *msg)
1983
SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
1984
const gchar *stream_id, *tmp;
1986
GibberXmppNode *si_node, *stream_node;
1988
unsigned long tube_id_tmp;
1989
SalutTubeIface *tube;
1990
GibberStanzaType type;
1991
GibberStanzaSubType sub_type;
1993
/* Caller is expected to have checked that we have a stream or muc-stream
1994
* node with a stream ID and the TUBES profile
1996
gibber_xmpp_stanza_get_type_info (msg, &type, &sub_type);
1997
g_return_if_fail (type == GIBBER_STANZA_TYPE_IQ);
1998
g_return_if_fail (sub_type == GIBBER_STANZA_SUB_TYPE_SET);
2000
si_node = gibber_xmpp_node_get_child_ns (msg->node, "si",
2002
g_return_if_fail (si_node != NULL);
2004
if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
2005
stream_node = gibber_xmpp_node_get_child_ns (si_node,
2006
"stream", GIBBER_TELEPATHY_NS_TUBES);
2008
stream_node = gibber_xmpp_node_get_child_ns (si_node,
2009
"muc-stream", GIBBER_TELEPATHY_NS_TUBES);
2010
g_return_if_fail (stream_node != NULL);
2012
stream_id = gibber_xmpp_node_get_attribute (si_node, "id");
2013
g_return_if_fail (stream_id != NULL);
2015
tmp = gibber_xmpp_node_get_attribute (stream_node, "tube");
2018
GError e = { GIBBER_XMPP_ERROR, XMPP_ERROR_BAD_REQUEST,
2019
"<stream> or <muc-stream> has no tube attribute" };
2021
DEBUG ("%s", e.message);
2022
gibber_bytestream_iface_close (bytestream, &e);
2025
tube_id_tmp = strtoul (tmp, &endptr, 10);
2026
if (!endptr || *endptr || tube_id_tmp > G_MAXUINT32)
2028
GError e = { GIBBER_XMPP_ERROR, XMPP_ERROR_BAD_REQUEST,
2029
"<stream> or <muc-stream> tube attribute not numeric or > 2**32" };
2031
DEBUG ("tube id is not numeric or > 2**32: %s", tmp);
2032
gibber_bytestream_iface_close (bytestream, &e);
2035
tube_id = (guint) tube_id_tmp;
2037
tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
2040
GError e = { GIBBER_XMPP_ERROR, XMPP_ERROR_BAD_REQUEST,
2041
"<stream> or <muc-stream> tube attribute points to a nonexistent "
2044
DEBUG ("tube %u doesn't exist", tube_id);
2045
gibber_bytestream_iface_close (bytestream, &e);
2049
DEBUG ("received new bytestream request for existing tube: %u", tube_id);
2051
salut_tube_iface_add_bytestream (tube, bytestream);
1848
2055
tubes_iface_init (gpointer g_iface,
1849
2056
gpointer iface_data)
1851
SalutSvcChannelTypeTubesClass *klass = (SalutSvcChannelTypeTubesClass *)g_iface;
2058
TpSvcChannelTypeTubesClass *klass = (TpSvcChannelTypeTubesClass *) g_iface;
1853
#define IMPLEMENT(x) salut_svc_channel_type_tubes_implement_##x (\
2060
#define IMPLEMENT(x) tp_svc_channel_type_tubes_implement_##x (\
1854
2061
klass, salut_tubes_channel_##x)
1855
2062
IMPLEMENT(get_available_tube_types);
1856
2063
IMPLEMENT(list_tubes);
1857
IMPLEMENT(offer_tube);
2064
IMPLEMENT(close_tube);
1859
2065
IMPLEMENT(offer_d_bus_tube);
1860
IMPLEMENT(offer_stream_unix_tube);
1862
IMPLEMENT(accept_tube);
1863
IMPLEMENT(close_tube);
1864
IMPLEMENT(get_d_bus_server_address);
2066
IMPLEMENT(accept_d_bus_tube);
2067
IMPLEMENT(get_d_bus_tube_address);
1865
2068
IMPLEMENT(get_d_bus_names);
1867
IMPLEMENT(get_stream_unix_socket_address);
2069
IMPLEMENT(offer_stream_tube);
2070
IMPLEMENT(accept_stream_tube);
2071
IMPLEMENT(get_stream_tube_socket_address);
2072
IMPLEMENT(get_available_stream_tube_types);
1869
2073
#undef IMPLEMENT