diff options
author | Jonny Lamb <jonny.lamb@collabora.co.uk> | 2011-03-02 15:17:20 +0000 |
---|---|---|
committer | Jonny Lamb <jonny.lamb@collabora.co.uk> | 2011-03-02 15:19:27 +0000 |
commit | 437ecdf19f385a28d3a9ac4a92a3dfaa732b2695 (patch) | |
tree | 893d53d730634f36f8f8673487266b5f71d959cd /lib/gibber | |
parent | e56b5d3319ce696568fd813361b7ec742c8704ee (diff) | |
download | telepathy-salut-437ecdf19f385a28d3a9ac4a92a3dfaa732b2695.tar.gz |
bytestream-oob: stop using GibberXmppConnections
Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk>
Diffstat (limited to 'lib/gibber')
-rw-r--r-- | lib/gibber/gibber-bytestream-oob.c | 365 |
1 files changed, 210 insertions, 155 deletions
diff --git a/lib/gibber/gibber-bytestream-oob.c b/lib/gibber/gibber-bytestream-oob.c index 51c887cd..64a0fa5e 100644 --- a/lib/gibber/gibber-bytestream-oob.c +++ b/lib/gibber/gibber-bytestream-oob.c @@ -28,10 +28,13 @@ #include <glib.h> +#include <wocky/wocky-stanza.h> +#include <wocky/wocky-porter.h> +#include <wocky/wocky-meta-porter.h> + #include "gibber-sockets.h" #include "gibber-bytestream-iface.h" #include "gibber-xmpp-connection.h" -#include <wocky/wocky-stanza.h> #include "gibber-namespaces.h" #include "gibber-linklocal-transport.h" #include "gibber-xmpp-error.h" @@ -57,7 +60,8 @@ G_DEFINE_TYPE_WITH_CODE (GibberBytestreamOOB, gibber_bytestream_oob, /* properties */ enum { - PROP_XMPP_CONNECTION = 1, + PROP_PORTER = 1, + PROP_CONTACT, PROP_SELF_ID, PROP_PEER_ID, PROP_STREAM_ID, @@ -71,7 +75,8 @@ enum typedef struct _GibberBytestreamIBBPrivate GibberBytestreamOOBPrivate; struct _GibberBytestreamIBBPrivate { - GibberXmppConnection *xmpp_connection; + WockyPorter *porter; + WockyContact *contact; gchar *self_id; gchar *peer_id; gchar *stream_id; @@ -79,8 +84,10 @@ struct _GibberBytestreamIBBPrivate /* ID of the OOB opening stanza. We'll reply to * it when we the bytestream is closed */ gchar *stream_open_id; + guint stanza_received_id; GibberBytestreamState state; gchar *host; + gchar *url; /* Are we the recipient of this bytestream? * If not we are the sender */ @@ -235,53 +242,30 @@ set_transport (GibberBytestreamOOB *self, } static void -connect_to_url (GibberBytestreamOOB *self, - const gchar *url) +connect_to_url (GibberBytestreamOOB *self) { GibberBytestreamOOBPrivate *priv = GIBBER_BYTESTREAM_OOB_GET_PRIVATE (self); GibberLLTransport *ll_transport; + GSocketConnection *conn; + GSocketAddress *socket_address = NULL; + GInetAddress *address; gchar **tokens; union { struct sockaddr_storage storage; struct sockaddr_in in; } addr; - socklen_t len; - const gchar *host, *port; + const gchar *port; gint portnum = 0; - - if (!g_str_has_prefix (url, "x-tcp://")) - { - GError e = { GIBBER_XMPP_ERROR, XMPP_ERROR_ITEM_NOT_FOUND, - "URL is not a TCP URL" }; - - DEBUG ("URL is not a TCP URL: %s. Close the bytestream", url); - gibber_bytestream_iface_close (GIBBER_BYTESTREAM_IFACE (self), &e); - return; - } + const gchar *url; + GError *error = NULL; /* TODO: if we want to support IPv6 literals, we have to remove * [] around the address */ - url += strlen ("x-tcp://"); + url = priv->url + strlen ("x-tcp://"); tokens = g_strsplit (url, ":", 2); - host = tokens[0]; port = tokens[1]; - /* FIXME, this is very specific to salut and won't work with a normal xmpp - * client */ - if (!gibber_transport_get_peeraddr ( - GIBBER_TRANSPORT (priv->xmpp_connection->transport), - &addr.storage, &len)) - { - /* I'm too lazy to create more specific errors for this as it should - * never happen while using salut anyway.. */ - GError e = { GIBBER_XMPP_ERROR, XMPP_ERROR_ITEM_NOT_FOUND, - "Unsable get socket address for the control connection" }; - DEBUG ("Could not get socket address for the control connection" ); - gibber_bytestream_iface_close (GIBBER_BYTESTREAM_IFACE (self), &e); - goto out; - } - if (port != NULL) portnum = atoi (port); @@ -296,6 +280,36 @@ connect_to_url (GibberBytestreamOOB *self, goto out; } + conn = wocky_meta_porter_borrow_connection (WOCKY_META_PORTER (priv->porter), + priv->contact); + + if (conn != NULL) + socket_address = g_socket_connection_get_remote_address (conn, NULL); + + if (conn == NULL || socket_address == NULL) + { + /* I'm too lazy to create more specific errors for this as it should + * never happen while using salut anyway.. */ + GError e = { GIBBER_XMPP_ERROR, XMPP_ERROR_ITEM_NOT_FOUND, + "Unsable get socket address for the control connection" }; + DEBUG ("Could not get socket address for the control connection" ); + gibber_bytestream_iface_close (GIBBER_BYTESTREAM_IFACE (self), &e); + goto out; + } + + if (!g_socket_address_to_native (G_SOCKET_ADDRESS (address), &(addr.storage), + sizeof (addr.storage), &error)) + { + GError e = { GIBBER_XMPP_ERROR, XMPP_ERROR_ITEM_NOT_FOUND, + "Failed to turn socket address into bytes" }; + DEBUG ("Failed to get native socket address: %s", error->message); + gibber_bytestream_iface_close (GIBBER_BYTESTREAM_IFACE (self), &e); + g_clear_error (&error); + goto out; + } + + g_object_unref (socket_address); + addr.in.sin_port = g_htons ((guint16) portnum); ll_transport = gibber_ll_transport_new (); @@ -307,6 +321,31 @@ out: g_strfreev (tokens); } +static void +opened_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + WockyMetaPorter *porter = WOCKY_META_PORTER (source_object); + GibberBytestreamOOB *self = user_data; + GibberBytestreamOOBPrivate *priv = GIBBER_BYTESTREAM_OOB_GET_PRIVATE (self); + GError *error = NULL; + + if (!wocky_meta_porter_open_finish (porter, result, &error)) + { + DEBUG ("failed to open connection to contact"); + g_clear_error (&error); + } + else + { + connect_to_url (self); + } + + g_free (priv->url); + + wocky_meta_porter_unref (porter, priv->contact); +} + static gboolean parse_oob_init_iq (GibberBytestreamOOB *self, WockyStanza *stanza) @@ -342,7 +381,20 @@ parse_oob_init_iq (GibberBytestreamOOB *self, priv->stream_open_id = g_strdup (wocky_node_get_attribute ( node, "id")); - connect_to_url (self, url); + if (!g_str_has_prefix (url, "x-tcp://")) + { + GError e = { GIBBER_XMPP_ERROR, XMPP_ERROR_ITEM_NOT_FOUND, + "URL is not a TCP URL" }; + + DEBUG ("URL is not a TCP URL: %s. Close the bytestream", priv->url); + gibber_bytestream_iface_close (GIBBER_BYTESTREAM_IFACE (self), &e); + return TRUE; + } + + priv->url = g_strdup (url); + + wocky_meta_porter_open_async (WOCKY_META_PORTER (priv->porter), + priv->contact, NULL, opened_cb, self); return TRUE; } @@ -378,10 +430,10 @@ parse_oob_iq_result (GibberBytestreamOOB *self, return TRUE; } -static void -xmpp_connection_received_stanza_cb (GibberXmppConnection *conn, - WockyStanza *stanza, - gpointer user_data) +static gboolean +received_stanza_cb (WockyPorter *porter, + WockyStanza *stanza, + gpointer user_data) { GibberBytestreamOOB *self = (GibberBytestreamOOB *) user_data; WockyNode *node = wocky_stanza_get_top_node (stanza); @@ -392,44 +444,16 @@ xmpp_connection_received_stanza_cb (GibberXmppConnection *conn, if (from == NULL) { DEBUG ("got a message without a from field"); - return; + return FALSE; } if (parse_oob_init_iq (self, stanza)) - return; + return TRUE; if (parse_oob_iq_result (self, stanza)) - return; -} + return TRUE; -static void -xmpp_connection_stream_closed_cb (GibberXmppConnection *connection, - gpointer userdata) -{ - GibberBytestreamOOB *self = GIBBER_BYTESTREAM_OOB (userdata); - DEBUG ("XMPP connection: stream closed. Close the OOB bytestream"); - g_object_set (self, "state", GIBBER_BYTESTREAM_STATE_CLOSING, NULL); - bytestream_closed (self); -} - -static void -xmpp_connection_transport_disconnected_cb (GibberLLTransport *transport, - gpointer userdata) -{ - GibberBytestreamOOB *self = GIBBER_BYTESTREAM_OOB (userdata); - DEBUG ("XMPP connection transport closed. Close the OOB bytestream"); - g_object_set (self, "state", GIBBER_BYTESTREAM_STATE_CLOSING, NULL); - bytestream_closed (self); -} - -static void -xmpp_connection_parse_error_cb (GibberXmppConnection *connection, - gpointer userdata) -{ - GibberBytestreamOOB *self = GIBBER_BYTESTREAM_OOB (userdata); - DEBUG ("XMPP connection: parse error. Close the OOB bytestream"); - g_object_set (self, "state", GIBBER_BYTESTREAM_STATE_CLOSING, NULL); - bytestream_closed (self); + return FALSE; } static void @@ -461,13 +485,18 @@ gibber_bytestream_oob_dispose (GObject *object) priv->listener = NULL; } - if (priv->xmpp_connection != NULL) + if (priv->porter != NULL) { - g_signal_handlers_disconnect_matched (priv->xmpp_connection->transport, - G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self); - g_signal_handlers_disconnect_matched (priv->xmpp_connection, - G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self); - g_object_unref (priv->xmpp_connection); + wocky_porter_unregister_handler (priv->porter, priv->stanza_received_id); + priv->stanza_received_id = 0; + g_object_unref (priv->porter); + priv->porter = NULL; + } + + if (priv->contact != NULL) + { + g_object_unref (priv->contact); + priv->contact = NULL; } G_OBJECT_CLASS (gibber_bytestream_oob_parent_class)->dispose (object); @@ -500,8 +529,11 @@ gibber_bytestream_oob_get_property (GObject *object, switch (property_id) { - case PROP_XMPP_CONNECTION: - g_value_set_object (value, priv->xmpp_connection); + case PROP_PORTER: + g_value_set_object (value, priv->porter); + break; + case PROP_CONTACT: + g_value_set_object (value, priv->contact); break; case PROP_SELF_ID: g_value_set_string (value, priv->self_id); @@ -531,6 +563,27 @@ gibber_bytestream_oob_get_property (GObject *object, } static void +make_porter_connections (GibberBytestreamOOB *self) +{ + GibberBytestreamOOBPrivate *priv = GIBBER_BYTESTREAM_OOB_GET_PRIVATE (self); + static gboolean done = FALSE; + gchar *jid; + + if (done) + return; + + jid = wocky_contact_dup_jid (priv->contact); + + priv->stanza_received_id = wocky_porter_register_handler_from (priv->porter, + WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_TYPE_NONE, jid, + WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, received_stanza_cb, self, NULL); + + g_free (jid); + + done = TRUE; +} + +static void gibber_bytestream_oob_set_property (GObject *object, guint property_id, const GValue *value, @@ -541,17 +594,17 @@ gibber_bytestream_oob_set_property (GObject *object, switch (property_id) { - case PROP_XMPP_CONNECTION: - priv->xmpp_connection = g_value_get_object (value); - g_signal_connect (priv->xmpp_connection, "received-stanza", - G_CALLBACK (xmpp_connection_received_stanza_cb), self); - g_signal_connect (priv->xmpp_connection, "stream-closed", - G_CALLBACK (xmpp_connection_stream_closed_cb), self); - g_signal_connect (priv->xmpp_connection->transport, "disconnected", - G_CALLBACK (xmpp_connection_transport_disconnected_cb), self); - g_signal_connect (priv->xmpp_connection, "parse-error", - G_CALLBACK (xmpp_connection_parse_error_cb), self); - g_object_ref (priv->xmpp_connection); + case PROP_PORTER: + priv->porter = g_value_dup_object (value); + + if (priv->porter != NULL && priv->contact != NULL) + make_porter_connections (self); + break; + case PROP_CONTACT: + priv->contact = g_value_dup_object (value); + + if (priv->porter != NULL && priv->contact != NULL) + make_porter_connections (self); break; case PROP_SELF_ID: g_free (priv->self_id); @@ -602,7 +655,8 @@ gibber_bytestream_oob_constructor (GType type, g_assert (priv->self_id != NULL); g_assert (priv->peer_id != NULL); g_assert (priv->stream_id != NULL); - g_assert (priv->xmpp_connection != NULL); + g_assert (priv->porter != NULL); + g_assert (priv->contact != NULL); return obj; } @@ -636,14 +690,25 @@ gibber_bytestream_oob_class_init ( "protocol"); param_spec = g_param_spec_object ( - "xmpp-connection", - "GibberXmppConnection object", - "Gibber XMPP connection object used for communication by this " + "porter", + "WockyPorter object", + "Wocky porter object used for communication by this " + "bytestream if it's a private one", + WOCKY_TYPE_PORTER, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_PORTER, + param_spec); + + param_spec = g_param_spec_object ( + "contact", + "WockyContact object", + "Contact object used for communication by this " "bytestream if it's a private one", - GIBBER_TYPE_XMPP_CONNECTION, + WOCKY_TYPE_CONTACT, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_XMPP_CONNECTION, + g_object_class_install_property (object_class, PROP_CONTACT, param_spec); param_spec = g_param_spec_string ( @@ -719,26 +784,26 @@ create_si_accept_iq (GibberBytestreamOOB *self) { GibberBytestreamOOBPrivate *priv = GIBBER_BYTESTREAM_OOB_GET_PRIVATE (self); - return wocky_stanza_build ( + return wocky_stanza_build_to_contact ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, - priv->self_id, priv->peer_id, - WOCKY_NODE_ATTRIBUTE, "id", priv->stream_init_id, - WOCKY_NODE_START, "si", - WOCKY_NODE_XMLNS, GIBBER_XMPP_NS_SI, - WOCKY_NODE_START, "feature", - WOCKY_NODE_XMLNS, GIBBER_XMPP_NS_FEATURENEG, - WOCKY_NODE_START, "x", - WOCKY_NODE_XMLNS, GIBBER_XMPP_NS_DATA, - WOCKY_NODE_ATTRIBUTE, "type", "submit", - WOCKY_NODE_START, "field", - WOCKY_NODE_ATTRIBUTE, "var", "stream-method", - WOCKY_NODE_START, "value", - WOCKY_NODE_TEXT, GIBBER_XMPP_NS_IQ_OOB, - WOCKY_NODE_END, - WOCKY_NODE_END, - WOCKY_NODE_END, - WOCKY_NODE_END, - WOCKY_NODE_END, NULL); + priv->self_id, priv->contact, + '@', "id", priv->stream_init_id, + '(', "si", + ':', GIBBER_XMPP_NS_SI, + '(', "feature", + ':', GIBBER_XMPP_NS_FEATURENEG, + '(', "x", + ':', GIBBER_XMPP_NS_DATA, + '@', "type", "submit", + '(', "field", + '@', "var", "stream-method", + '(', "value", + '$', GIBBER_XMPP_NS_IQ_OOB, + ')', + ')', + ')', + ')', + ')', NULL); } /* @@ -775,7 +840,7 @@ gibber_bytestream_oob_accept (GibberBytestreamIface *bytestream, func (si, user_data); } - gibber_xmpp_connection_send (priv->xmpp_connection, stanza, NULL); + wocky_porter_send (priv->porter, stanza); DEBUG ("stream is now accepted"); g_object_set (self, "state", GIBBER_BYTESTREAM_STATE_ACCEPTED, NULL); @@ -789,27 +854,18 @@ bytestream_closed (GibberBytestreamOOB *self) if (priv->recipient) { - /* We are the recipient and so have to send the reply - * to the OOB opening IQ */ - if (priv->xmpp_connection->stream_flags == - GIBBER_XMPP_CONNECTION_STREAM_FULLY_OPEN) - { - WockyStanza *stanza; + WockyStanza *stanza; - /* As described in the XEP, we send result IQ when we have - * finished to use the OOB */ - stanza = make_iq_oob_sucess_response (priv->self_id, - priv->peer_id, priv->stream_open_id); + /* As described in the XEP, we send result IQ when we have + * finished to use the OOB */ + stanza = make_iq_oob_sucess_response (priv->self_id, + priv->peer_id, priv->stream_open_id); + wocky_stanza_set_contact (stanza, priv->contact); - DEBUG ("send OOB close stanza"); + DEBUG ("send OOB close stanza"); - gibber_xmpp_connection_send (priv->xmpp_connection, stanza, NULL); - g_object_unref (stanza); - } - else - { - DEBUG ("XMPP connection is closed. Don't send OOB close stanza"); - } + wocky_porter_send (priv->porter, stanza); + g_object_unref (stanza); } else { @@ -838,10 +894,10 @@ gibber_bytestream_oob_decline (GibberBytestreamOOB *self, g_return_if_fail (priv->state == GIBBER_BYTESTREAM_STATE_LOCAL_PENDING); - stanza = wocky_stanza_build ( + stanza = wocky_stanza_build_to_contact ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, - priv->self_id, priv->peer_id, - WOCKY_NODE_ATTRIBUTE, "id", priv->stream_init_id, + priv->self_id, priv->contact, + '@', "id", priv->stream_init_id, NULL); node = wocky_stanza_get_top_node (stanza); @@ -855,7 +911,7 @@ gibber_bytestream_oob_decline (GibberBytestreamOOB *self, "Offer Declined"); } - gibber_xmpp_connection_send (priv->xmpp_connection, stanza, NULL); + wocky_porter_send (priv->porter, stanza); g_object_unref (stanza); } @@ -912,13 +968,13 @@ make_oob_init_iq (const gchar *from, return wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, from, to, - WOCKY_NODE_START, "query", - WOCKY_NODE_XMLNS, GIBBER_XMPP_NS_IQ_OOB, - WOCKY_NODE_ATTRIBUTE, "sid", stream_id, - WOCKY_NODE_START, "url", - WOCKY_NODE_TEXT, url, - WOCKY_NODE_END, - WOCKY_NODE_END, NULL); + '(', "query", + ':', GIBBER_XMPP_NS_IQ_OOB, + '@', "sid", stream_id, + '(', "url", + '$', url, + ')', + ')', NULL); } static void @@ -955,7 +1011,6 @@ gibber_bytestream_oob_initiate (GibberBytestreamIface *bytestream) GibberBytestreamOOBPrivate *priv = GIBBER_BYTESTREAM_OOB_GET_PRIVATE (self); WockyStanza *stanza; WockyNode *node; - GError *error = NULL; const gchar *id; int port; gchar *url; @@ -988,25 +1043,25 @@ gibber_bytestream_oob_initiate (GibberBytestreamIface *bytestream) stanza = make_oob_init_iq (priv->self_id, priv->peer_id, priv->stream_id, url); g_free (url); + wocky_stanza_set_contact (stanza, priv->contact); node = wocky_stanza_get_top_node (stanza); id = wocky_node_get_attribute (node, "id"); if (id == NULL) { - priv->stream_open_id = gibber_xmpp_connection_new_id ( - priv->xmpp_connection); - wocky_node_set_attribute (node, "id", - priv->stream_open_id); + /* let the porter generate the IQ id for us */ + wocky_porter_send_iq_async (priv->porter, stanza, + NULL, NULL, NULL); + + priv->stream_open_id = g_strdup ( + wocky_node_get_attribute (node, "id")); } else { + /* save the stream open ID */ priv->stream_open_id = g_strdup (id); - } - if (!gibber_xmpp_connection_send (priv->xmpp_connection, stanza, &error)) - { - DEBUG ("can't send OOB init stanza: %s", error->message); - return FALSE; + wocky_porter_send (priv->porter, stanza); } g_object_unref (stanza); |