summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWill Thompson <will.thompson@collabora.co.uk>2012-10-31 20:19:18 +0000
committerWill Thompson <will.thompson@collabora.co.uk>2012-12-06 18:28:32 +0000
commita990012f6e48af641686741ea52506230cdcaaad (patch)
tree5d541acd4b7dcb3eeee22d993fb6984940b9db7e /src
parentc33a817b5bcf9f6bec7c744e4c5a3f0b96df4118 (diff)
Emit delivery reports for XEP-0184 receipts.
Diffstat (limited to 'src')
-rw-r--r--src/im-channel.c32
-rw-r--r--src/im-channel.h3
-rw-r--r--src/im-factory.c47
-rw-r--r--src/namespaces.h1
4 files changed, 74 insertions, 9 deletions
diff --git a/src/im-channel.c b/src/im-channel.c
index 1d1cf2fa5..c6e40b58a 100644
--- a/src/im-channel.c
+++ b/src/im-channel.c
@@ -476,7 +476,7 @@ _gabble_im_channel_report_delivery (
TpBaseChannel *base_chan = (TpBaseChannel *) self;
TpBaseConnection *base_conn;
TpHandle peer;
- TpMessage *msg, *delivery_report;
+ TpMessage *delivery_report;
gchar *tmp;
g_return_if_fail (GABBLE_IS_IM_CHANNEL (self));
@@ -495,7 +495,6 @@ _gabble_im_channel_report_delivery (
priv->chat_states_supported = CHAT_STATES_UNKNOWN;
}
- msg = build_message (self, type, timestamp, text);
delivery_report = tp_cm_message_new (base_conn, 1);
tp_message_set_uint32 (delivery_report, 0, "message-type",
TP_CHANNEL_TEXT_MESSAGE_TYPE_DELIVERY_REPORT);
@@ -514,15 +513,20 @@ _gabble_im_channel_report_delivery (
if (id != NULL)
tp_message_set_string (delivery_report, 0, "delivery-token", id);
- /* This is a delivery report, so the original sender of the echoed message
- * must be us! */
- tp_cm_message_set_sender (msg, tp_base_connection_get_self_handle (base_conn));
+ if (text != NULL)
+ {
+ TpMessage *msg = build_message (self, type, timestamp, text);
+ /* This is a delivery report, so the original sender of the echoed message
+ * must be us! */
+ tp_cm_message_set_sender (msg, tp_base_connection_get_self_handle (base_conn));
- /* Since this is a delivery report, we can trust the id on the message. */
- if (id != NULL)
- tp_message_set_string (msg, 0, "message-token", id);
+ /* Since this is a delivery report, we can trust the id on the message. */
+ if (id != NULL)
+ tp_message_set_string (msg, 0, "message-token", id);
+
+ tp_cm_message_take_message (delivery_report, 0, "delivery-echo", msg);
+ }
- tp_cm_message_take_message (delivery_report, 0, "delivery-echo", msg);
tp_message_mixin_take_received (G_OBJECT (self), delivery_report);
}
@@ -550,6 +554,16 @@ _gabble_im_channel_state_receive (GabbleIMChannel *chan,
tp_base_channel_get_target_handle (base_chan), state);
}
+void
+gabble_im_channel_receive_receipt (
+ GabbleIMChannel *self,
+ const gchar *receipt_id)
+{
+ _gabble_im_channel_report_delivery (self,
+ TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, 0, receipt_id, NULL,
+ GABBLE_TEXT_CHANNEL_SEND_NO_ERROR, TP_DELIVERY_STATUS_DELIVERED);
+}
+
static void
gabble_im_channel_close (TpBaseChannel *base_chan)
{
diff --git a/src/im-channel.h b/src/im-channel.h
index 076565ef5..4b6fc7bee 100644
--- a/src/im-channel.h
+++ b/src/im-channel.h
@@ -71,6 +71,9 @@ void _gabble_im_channel_receive (GabbleIMChannel *chan,
gint state);
void _gabble_im_channel_state_receive (GabbleIMChannel *chan,
TpChannelChatState state);
+void gabble_im_channel_receive_receipt (
+ GabbleIMChannel *self,
+ const gchar *receipt_id);
void _gabble_im_channel_report_delivery (
GabbleIMChannel *self,
diff --git a/src/im-factory.c b/src/im-factory.c
index 661f6fbc1..e0bff2bdf 100644
--- a/src/im-factory.c
+++ b/src/im-factory.c
@@ -60,6 +60,7 @@ struct _GabbleImFactoryPrivate
{
GabbleConnection *conn;
guint message_cb_id;
+ guint delivery_report_cb_id;
GHashTable *channels;
gulong status_changed_id;
@@ -266,6 +267,42 @@ im_factory_message_cb (
return TRUE;
}
+/* Signals incoming delivery receipts. http://xmpp.org/extensions/xep-0184.html
+ */
+static gboolean
+im_factory_receipt_cb (
+ WockyPorter *porter,
+ WockyStanza *message,
+ gpointer user_data)
+{
+ GabbleImFactory *self = GABBLE_IM_FACTORY (user_data);
+ WockyNode *received;
+ const gchar *from, *received_id;
+ GabbleIMChannel *channel;
+
+ received = wocky_node_get_child_ns (wocky_stanza_get_top_node (message),
+ "received", NS_RECEIPTS);
+ g_return_val_if_fail (received != NULL, FALSE);
+
+ received_id = wocky_node_get_attribute (received, "id");
+ if (received_id == NULL)
+ {
+ STANZA_DEBUG (message, "but *what* did you receive?!");
+ return TRUE;
+ }
+
+ from = wocky_stanza_get_from (message);
+ channel = get_channel_for_incoming_message (self, from, FALSE);
+ if (channel == NULL)
+ {
+ DEBUG ("no existing channel with '%s'; ignoring receipt", from);
+ return TRUE;
+ }
+
+ gabble_im_channel_receive_receipt (channel, received_id);
+ return TRUE;
+}
+
/**
* im_channel_closed_cb:
*
@@ -433,6 +470,10 @@ gabble_im_factory_close_all (GabbleImFactory *self)
wocky_porter_unregister_handler (porter, self->priv->message_cb_id);
self->priv->message_cb_id = 0;
+
+ wocky_porter_unregister_handler (porter, self->priv->delivery_report_cb_id);
+ self->priv->delivery_report_cb_id = 0;
+
g_object_unref (porter);
}
}
@@ -519,6 +560,12 @@ porter_available_cb (
WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE,
WOCKY_PORTER_HANDLER_PRIORITY_MIN, im_factory_message_cb, self,
NULL);
+ self->priv->delivery_report_cb_id = wocky_porter_register_handler_from_anyone (porter,
+ WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE,
+ WOCKY_PORTER_HANDLER_PRIORITY_MIN, im_factory_receipt_cb, self,
+ '(',
+ "received", ':', NS_RECEIPTS,
+ ')', NULL);
g_object_get (conn, "stream-server", &stream_server, NULL);
diff --git a/src/namespaces.h b/src/namespaces.h
index 0d06d7d54..2a2d8f91b 100644
--- a/src/namespaces.h
+++ b/src/namespaces.h
@@ -103,6 +103,7 @@
#define NS_PRESENCE_INVISIBLE "presence-invisible"
#define NS_PRIVACY "jabber:iq:privacy"
#define NS_INVISIBLE "urn:xmpp:invisible:0"
+#define NS_RECEIPTS "urn:xmpp:receipts"
#define NS_REGISTER "jabber:iq:register"
#define NS_ROSTER "jabber:iq:roster"
#define NS_SEARCH "jabber:iq:search"