[Telepathy-commits] [telepathy-salut/master] Stream tube object sends a close tube message when the tube is close. It has a reference on the XmppConnectionManager to request a connection. When a close tube message is received, close the tube.
Alban Crequy
alban.crequy at collabora.co.uk
Tue Nov 25 03:59:13 PST 2008
20080721114615-a41c0-e516a921271f991b7a7ab359e070a5f5ba8ff190.gz
---
src/salut-tubes-channel.c | 26 +++++++-
src/salut-tubes-channel.h | 3 +
src/salut-tubes-manager.c | 90 ++++++++++++++++++----------
src/tube-stream.c | 147 ++++++++++++++++++++++++++++++++++-----------
src/tube-stream.h | 7 +-
5 files changed, 201 insertions(+), 72 deletions(-)
diff --git a/src/salut-tubes-channel.c b/src/salut-tubes-channel.c
index 964d9d7..ae047c4 100644
--- a/src/salut-tubes-channel.c
+++ b/src/salut-tubes-channel.c
@@ -943,6 +943,27 @@ tubes_message_received (SalutTubesChannel *self,
}
}
+void tubes_message_close_received (SalutTubesChannel *self,
+ TpHandle initiator_handle,
+ guint tube_id)
+{
+ SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
+
+ SalutTubeIface *tube;
+
+ tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
+
+ if (tube)
+ {
+ DEBUG ("received a tube close message");
+ salut_tube_iface_close (tube);
+ }
+ else
+ {
+ DEBUG ("received a tube close message on a non existant tube");
+ }
+}
+
static void
muc_connection_new_senders_cb (GibberMucConnection *conn,
GArray *senders,
@@ -1142,8 +1163,8 @@ create_new_tube (SalutTubesChannel *self,
break;
case TP_TUBE_TYPE_STREAM:
tube = SALUT_TUBE_IFACE (salut_tube_stream_new (priv->conn,
- priv->handle, priv->handle_type, priv->self_handle, initiator,
- service, parameters, tube_id));
+ priv->xmpp_connection_manager, priv->handle, priv->handle_type,
+ priv->self_handle, initiator, service, parameters, tube_id));
break;
default:
g_assert_not_reached ();
@@ -1889,6 +1910,7 @@ _send_channel_iq_tube (gpointer key,
g_error_free (error);
}
+ g_object_unref (stanza);
g_free (tube_id_str);
}
diff --git a/src/salut-tubes-channel.h b/src/salut-tubes-channel.h
index 932f6f7..4941f9f 100644
--- a/src/salut-tubes-channel.h
+++ b/src/salut-tubes-channel.h
@@ -75,6 +75,9 @@ void tubes_message_received (SalutTubesChannel *self,
const gchar *service, TpTubeType tube_type, TpHandle initiator_handle,
GHashTable *parameters, guint tube_id);
+void tubes_message_close_received (SalutTubesChannel *self,
+ TpHandle initiator_handle, guint tube_id);
+
G_END_DECLS
#endif /* #ifndef __SALUT_TUBES_CHANNEL_H__*/
diff --git a/src/salut-tubes-manager.c b/src/salut-tubes-manager.c
index 2dd7242..0905505 100644
--- a/src/salut-tubes-manager.c
+++ b/src/salut-tubes-manager.c
@@ -127,6 +127,7 @@ iq_tube_request_filter (SalutXmppConnectionManager *xcm,
static gboolean
extract_tube_information (TpHandleRepoIface *contact_repo,
GibberXmppStanza *stanza,
+ gboolean *close,
TpTubeType *type,
TpHandle *initiator_handle,
const gchar **service,
@@ -134,7 +135,8 @@ extract_tube_information (TpHandleRepoIface *contact_repo,
guint *tube_id)
{
GibberXmppNode *iq;
- GibberXmppNode *tube_node;
+ GibberXmppNode *tube_node, *close_node, *node;
+ gboolean _close;
iq = stanza->node;
@@ -159,13 +161,35 @@ extract_tube_information (TpHandleRepoIface *contact_repo,
tube_node = gibber_xmpp_node_get_child_ns (iq, "tube",
GIBBER_TELEPATHY_NS_TUBES);
- if (tube_node == NULL)
+ close_node = gibber_xmpp_node_get_child_ns (iq, "close",
+ GIBBER_TELEPATHY_NS_TUBES);
+
+ if (tube_node == NULL && close_node == NULL)
{
- DEBUG ("The <iq> does not have a <tube>");
+ DEBUG ("The <iq> does not have a <tube> nor a <close>");
return FALSE;
}
+ if (tube_node != NULL && close_node != NULL)
+ {
+ DEBUG ("The <iq> has both a <tube> nor a <close>");
+ return FALSE;
+ }
+ if (tube_node != NULL)
+ {
+ node = tube_node;
+ }
+ else
+ {
+ node = close_node;
+ }
+
+ _close = close_node != NULL;
+ if (close != NULL)
+ {
+ *close = _close;
+ }
- if (type != NULL)
+ if (!_close && type != NULL)
{
const gchar *tube_type;
@@ -181,12 +205,12 @@ extract_tube_information (TpHandleRepoIface *contact_repo,
}
}
- if (service != NULL)
+ if (!_close && service != NULL)
{
*service = gibber_xmpp_node_get_attribute (tube_node, "service");
}
- if (parameters != NULL)
+ if (!_close && parameters != NULL)
{
GibberXmppNode *node;
@@ -201,10 +225,10 @@ extract_tube_information (TpHandleRepoIface *contact_repo,
gchar *endptr;
long int tmp;
- str = gibber_xmpp_node_get_attribute (tube_node, "id");
+ str = gibber_xmpp_node_get_attribute (node, "id");
if (str == NULL)
{
- DEBUG ("no tube id in SI request");
+ DEBUG ("no tube id in tube request");
return FALSE;
}
@@ -231,55 +255,57 @@ iq_tube_request_cb (SalutXmppConnectionManager *xcm,
TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
(TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
- GibberXmppNode *close;
GibberXmppStanza *reply;
/* tube informations */
- const gchar *service;
- TpTubeType tube_type;
+ const gchar *service = NULL;
+ TpTubeType tube_type = TP_TUBE_TYPE_DBUS;
TpHandle initiator_handle;
- GHashTable *parameters;
+ GHashTable *parameters = NULL;
guint tube_id;
+ gboolean close;
SalutTubesChannel *chan;
/* after this point, the message is for us, so in all cases we either handle
* it or send an error reply */
- close = gibber_xmpp_node_get_child_ns (stanza->node, "close",
- GIBBER_TELEPATHY_NS_TUBES);
- if (close != NULL)
- {
- DEBUG ("received a close tube request. Not implemented.");
- return;
- }
-
- if (!extract_tube_information (contact_repo, stanza, &tube_type,
+ if (!extract_tube_information (contact_repo, stanza, &close, &tube_type,
&initiator_handle, &service, ¶meters, &tube_id))
{
GibberXmppStanza *reply;
reply = gibber_iq_helper_new_error_reply (stanza, XMPP_ERROR_BAD_REQUEST,
- "failed to parse SI request");
+ "failed to parse tube request");
gibber_xmpp_connection_send (conn, reply, NULL);
g_object_unref (reply);
return;
}
- DEBUG ("received a tube request of type %d, tube_id %d", tube_type, tube_id);
+ DEBUG ("received a tube request, tube_id %d", tube_id);
chan = g_hash_table_lookup (priv->channels,
GUINT_TO_POINTER (initiator_handle));
- if (chan == NULL)
- {
- chan = new_tubes_channel (self, initiator_handle);
- tp_channel_factory_iface_emit_new_channel (self,
- (TpChannelIface *) chan, NULL);
- }
-
- tubes_message_received (chan, service, tube_type, initiator_handle,
- parameters, tube_id);
+ if (close)
+ {
+ if (chan != NULL)
+ {
+ tubes_message_close_received (chan, initiator_handle, tube_id);
+ }
+ }
+ else
+ {
+ if (chan == NULL)
+ {
+ chan = new_tubes_channel (self, initiator_handle);
+ tp_channel_factory_iface_emit_new_channel (self,
+ (TpChannelIface *) chan, NULL);
+ }
+
+ tubes_message_received (chan, service, tube_type, initiator_handle,
+ parameters, tube_id);
+ }
reply = gibber_iq_helper_new_result_reply (stanza);
gibber_xmpp_connection_send (conn, reply, NULL);
diff --git a/src/tube-stream.c b/src/tube-stream.c
index a6dfbea..0759404 100644
--- a/src/tube-stream.c
+++ b/src/tube-stream.c
@@ -38,6 +38,7 @@
#include <gibber/gibber-bytestream-iface.h>
#include <gibber/gibber-transport.h>
#include <gibber/gibber-fd-transport.h>
+#include <gibber/gibber-iq-helper.h>
#define DEBUG_FLAG DEBUG_TUBES
@@ -48,6 +49,7 @@
#include "tube-iface.h"
#include "salut-bytestream-manager.h"
#include "salut-contact-manager.h"
+#include "salut-xmpp-connection-manager.h"
static void
tube_iface_init (gpointer g_iface, gpointer iface_data);
@@ -88,6 +90,7 @@ static guint signals[LAST_SIGNAL] = {0};
enum
{
PROP_CONNECTION = 1,
+ PROP_CHANNEL,
PROP_HANDLE,
PROP_HANDLE_TYPE,
PROP_SELF_HANDLE,
@@ -101,6 +104,7 @@ enum
PROP_ADDRESS,
PROP_ACCESS_CONTROL,
PROP_ACCESS_CONTROL_PARAM,
+ PROP_XMPP_CONNECTION_MANAGER,
LAST_PROPERTY
};
@@ -131,6 +135,10 @@ struct _SalutTubeStreamPrivate
guint listen_io_channel_source_id;
gboolean closed;
+ /* we need to send an iq stanza to close the tube */
+ GibberIqHelper *iq_helper;
+ SalutXmppConnectionManager *xmpp_connection_manager;
+
gboolean offer_needed;
gboolean dispose_has_run;
@@ -915,6 +923,12 @@ salut_tube_stream_dispose (GObject *object)
priv->listen_io_channel = NULL;
}
+ if (priv->iq_helper != NULL)
+ {
+ g_object_unref (priv->iq_helper);
+ priv->iq_helper = NULL;
+ }
+
priv->dispose_has_run = TRUE;
if (G_OBJECT_CLASS (salut_tube_stream_parent_class)->dispose)
@@ -998,6 +1012,9 @@ salut_tube_stream_get_property (GObject *object,
case PROP_ACCESS_CONTROL_PARAM:
g_value_set_pointer (value, priv->access_control_param);
break;
+ case PROP_XMPP_CONNECTION_MANAGER:
+ g_value_set_object (value, priv->xmpp_connection_manager);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -1065,6 +1082,10 @@ salut_tube_stream_set_property (GObject *object,
g_value_get_pointer (value));
}
break;
+ case PROP_XMPP_CONNECTION_MANAGER:
+ priv->xmpp_connection_manager = g_value_get_object (value);
+ g_object_ref (priv->xmpp_connection_manager);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -1204,6 +1225,31 @@ salut_tube_stream_class_init (SalutTubeStreamClass *salut_tube_stream_class)
g_object_class_install_property (object_class, PROP_ACCESS_CONTROL_PARAM,
param_spec);
+ param_spec = g_param_spec_object (
+ "channel",
+ "SalutTubesChannel object",
+ "Salut Tubes Channel associated with this stream tube object",
+ SALUT_TYPE_TUBES_CHANNEL,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB);
+ g_object_class_install_property (object_class, PROP_CHANNEL,
+ param_spec);
+
+ param_spec = g_param_spec_object (
+ "xmpp-connection-manager",
+ "SalutXmppConnectionManager object",
+ "Salut XMPP Connection manager used for this tube channel in case of "
+ "1-1 tube",
+ SALUT_TYPE_XMPP_CONNECTION_MANAGER,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB);
+ g_object_class_install_property (object_class, PROP_XMPP_CONNECTION_MANAGER,
+ param_spec);
+
signals[OPENED] =
g_signal_new ("opened",
G_OBJECT_CLASS_TYPE (salut_tube_stream_class),
@@ -1262,6 +1308,7 @@ data_received_cb (GibberBytestreamIface *bytestream,
SalutTubeStream *
salut_tube_stream_new (SalutConnection *conn,
+ SalutXmppConnectionManager *xmpp_connection_manager,
TpHandle handle,
TpHandleType handle_type,
TpHandle self_handle,
@@ -1272,6 +1319,7 @@ salut_tube_stream_new (SalutConnection *conn,
{
return g_object_new (SALUT_TYPE_TUBE_STREAM,
"connection", conn,
+ "xmpp-connection-manager", xmpp_connection_manager,
"handle", handle,
"handle-type", handle_type,
"self-handle", self_handle,
@@ -1322,6 +1370,15 @@ salut_tube_stream_offer_needed (SalutTubeIface *tube)
return priv->offer_needed;
}
+static void
+iq_close_reply_cb (GibberIqHelper *helper,
+ GibberXmppStanza *sent_stanza,
+ GibberXmppStanza *reply_stanza,
+ GObject *object,
+ gpointer user_data)
+{
+}
+
/**
* salut_tube_stream_close
*
@@ -1342,43 +1399,63 @@ salut_tube_stream_close (SalutTubeIface *tube)
if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
{
- /* TODO: implement 1-1 tube */
-#if 0
- LmMessage *msg;
- const gchar *jid;
+ GibberXmppStanza *stanza;
+ const gchar *jid_from, *jid_to;
TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
(TpBaseConnection*) priv->conn, TP_HANDLE_TYPE_CONTACT);
- gchar *id_str;
-
- jid = tp_handle_inspect (contact_repo, priv->handle);
- id_str = g_strdup_printf ("%u", priv->id);
-
- /* Send the close message */
- msg = lm_message_build (jid, LM_MESSAGE_TYPE_MESSAGE,
- '(', "close", "",
- '@', "xmlns", NS_TUBES,
- '@', "tube", id_str,
- ')',
- '(', "amp", "",
- '@', "xmlns", NS_AMP,
- '(', "rule", "",
- '@', "condition", "deliver-at",
- '@', "value", "stored",
- '@', "action", "error",
- ')',
- '(', "rule", "",
- '@', "condition", "match-resource",
- '@', "value", "exact",
- '@', "action", "error",
- ')',
- ')',
- NULL);
- g_free (id_str);
-
- _salut_connection_send (priv->conn, msg, NULL);
-
- lm_message_unref (msg);
-#endif
+ gchar *tube_id_str;
+ GError *error = NULL;
+
+ jid_to = tp_handle_inspect (contact_repo, priv->handle);
+ jid_from = tp_handle_inspect (contact_repo, priv->self_handle);
+ tube_id_str = g_strdup_printf ("%u", priv->id);
+
+ stanza = gibber_xmpp_stanza_build (GIBBER_STANZA_TYPE_IQ,
+ GIBBER_STANZA_SUB_TYPE_SET,
+ jid_from, jid_to,
+ GIBBER_NODE, "close",
+ GIBBER_NODE_XMLNS, GIBBER_TELEPATHY_NS_TUBES,
+ GIBBER_NODE_ATTRIBUTE, "id", tube_id_str,
+ GIBBER_NODE_END,
+ GIBBER_STANZA_END);
+
+ if (priv->iq_helper == NULL)
+ {
+ SalutXmppConnectionManagerRequestConnectionResult result;
+ SalutContactManager *contact_mgr;
+ SalutContact *contact;
+ GibberXmppConnection *xmpp_connection = NULL;
+
+ g_object_get (priv->conn, "contact-manager", &contact_mgr, NULL);
+ g_assert (contact_mgr != NULL);
+
+ contact = salut_contact_manager_get_contact (contact_mgr,
+ priv->handle);
+
+ result = salut_xmpp_connection_manager_request_connection (
+ priv->xmpp_connection_manager, contact, &xmpp_connection, NULL);
+
+ if (result ==
+ SALUT_XMPP_CONNECTION_MANAGER_REQUEST_CONNECTION_RESULT_DONE)
+ {
+ priv->iq_helper = gibber_iq_helper_new (xmpp_connection);
+ g_assert (priv->iq_helper);
+ }
+ }
+
+ if (priv->iq_helper != NULL)
+ {
+ if (!gibber_iq_helper_send_with_reply (priv->iq_helper, stanza,
+ iq_close_reply_cb, G_OBJECT(self), tube, &error))
+ {
+ DEBUG ("ERROR: '%s'", error->message);
+ g_error_free (error);
+ }
+ }
+
+ g_free (tube_id_str);
+
+ g_object_unref (stanza);
}
g_signal_emit (G_OBJECT (self), signals[CLOSED], 0);
diff --git a/src/tube-stream.h b/src/tube-stream.h
index f770198..3472065 100644
--- a/src/tube-stream.h
+++ b/src/tube-stream.h
@@ -25,6 +25,7 @@
#include <telepathy-glib/enums.h>
#include "salut-connection.h"
+#include "salut-tubes-channel.h"
G_BEGIN_DECLS
@@ -60,9 +61,9 @@ GType salut_tube_stream_get_type (void);
SalutTubeStreamClass))
SalutTubeStream *salut_tube_stream_new (SalutConnection *conn,
- TpHandle handle, TpHandleType handle_type, TpHandle self_handle,
- TpHandle initiator, const gchar *service, GHashTable *parameters,
- guint id);
+ SalutXmppConnectionManager *xmpp_connection_manager, TpHandle handle,
+ TpHandleType handle_type, TpHandle self_handle, TpHandle initiator,
+ const gchar *service, GHashTable *parameters, guint id);
gboolean salut_tube_stream_check_params (TpSocketAddressType address_type,
const GValue *address, TpSocketAccessControl access_control,
--
1.5.6.5
More information about the Telepathy-commits
mailing list