changeset 1705:ac881b5f9248

Add /request ping (XEP-0199), by merging isbear's module
author Mikael Berthe <mikael@lilotux.net>
date Mon, 08 Feb 2010 21:23:05 +0100
parents ab502d645378
children a5263e93c5d7
files mcabber/mcabber/commands.c mcabber/mcabber/xmpp.c mcabber/mcabber/xmpp.h mcabber/mcabber/xmpp_iqrequest.c
diffstat 4 files changed, 104 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/mcabber/mcabber/commands.c	Mon Feb 08 19:36:56 2010 +0100
+++ b/mcabber/mcabber/commands.c	Mon Feb 08 21:23:05 2010 +0100
@@ -305,6 +305,7 @@
 
   // Request (query) category
   compl_add_category_word(COMPL_REQUEST, "last");
+  compl_add_category_word(COMPL_REQUEST, "ping");
   compl_add_category_word(COMPL_REQUEST, "time");
   compl_add_category_word(COMPL_REQUEST, "vcard");
   compl_add_category_word(COMPL_REQUEST, "version");
@@ -3242,6 +3243,8 @@
       numtype = iqreq_time;
     else if (!strcasecmp(type, "last"))
       numtype = iqreq_last;
+    else if (!strcasecmp(type, "ping"))
+      numtype = iqreq_ping;
     else if (!strcasecmp(type, "vcard"))
       numtype = iqreq_vcard;
   }
@@ -3290,6 +3293,7 @@
       case iqreq_time:
       case iqreq_last:
       case iqreq_vcard:
+      case iqreq_ping:
           xmpp_request(fjid, numtype);
           break;
       default:
--- a/mcabber/mcabber/xmpp.c	Mon Feb 08 19:36:56 2010 +0100
+++ b/mcabber/mcabber/xmpp.c	Mon Feb 08 21:23:05 2010 +0100
@@ -245,10 +245,12 @@
   } else if (reqtype == iqreq_last) {
     xmlns = NS_LAST;
     strreqtype = "last";
+  } else if (reqtype == iqreq_ping) {
+    xmlns = NS_PING;
+    strreqtype = "last";
   } else if (reqtype == iqreq_vcard) {
     xmlns = NS_VCARD;
     strreqtype = "vCard";
-    // Special case
   } else
     return;
 
--- a/mcabber/mcabber/xmpp.h	Mon Feb 08 19:36:56 2010 +0100
+++ b/mcabber/mcabber/xmpp.h	Mon Feb 08 21:23:05 2010 +0100
@@ -9,7 +9,8 @@
   iqreq_version,
   iqreq_time,
   iqreq_last,
-  iqreq_vcard
+  iqreq_vcard,
+  iqreq_ping
 };
 
 struct annotation {
--- a/mcabber/mcabber/xmpp_iqrequest.c	Mon Feb 08 19:36:56 2010 +0100
+++ b/mcabber/mcabber/xmpp_iqrequest.c	Mon Feb 08 21:23:05 2010 +0100
@@ -22,6 +22,7 @@
 
 #include <string.h>
 #include <stdlib.h>
+#include <sys/time.h>
 
 #include "xmpp_helper.h"
 #include "xmpp_iq.h"
@@ -42,6 +43,8 @@
                                LmMessage *m, gpointer user_data);
 static LmHandlerResult cb_last(LmMessageHandler *h, LmConnection *c,
                                LmMessage *m, gpointer user_data);
+static LmHandlerResult cb_ping(LmMessageHandler *h, LmConnection *c,
+                               LmMessage *m, gpointer user_data);
 static LmHandlerResult cb_vcard(LmMessageHandler *h, LmConnection *c,
                                LmMessage *m, gpointer user_data);
 
@@ -55,6 +58,7 @@
   {NS_VERSION,"query", &cb_version},
   {NS_TIME,   "query", &cb_time},
   {NS_LAST,   "query", &cb_last},
+  {NS_PING,   "ping",  &cb_ping},
   {NS_VCARD,  "vCard", &cb_vcard},
   {NULL, NULL, NULL}
 };
@@ -71,12 +75,86 @@
   vcard_pref    = 1<<7,
 };
 
-// xmlns has to be a namespace from iq_request_handlers[].xmlns
+static LmHandlerResult cb_ping(LmMessageHandler *h, LmConnection *c,
+                               LmMessage *message, gpointer udata)
+{
+  struct timeval *timestamp = (struct timeval *) udata;
+  struct timeval now;
+  time_t         dsec;
+  suseconds_t    dusec;
+
+  gettimeofday(&now, NULL);
+  dsec = now.tv_sec - timestamp->tv_sec;
+  if (now.tv_usec < timestamp->tv_usec) {
+    dusec = now.tv_usec + 1000000 - timestamp->tv_usec;
+    --dsec;
+  } else
+    dusec = now.tv_usec - timestamp->tv_usec;
+
+  switch (lm_message_get_sub_type(message)) {
+    case LM_MESSAGE_SUB_TYPE_RESULT:
+        { // print to buddy's buffer
+          LmMessageNode *node = lm_message_get_node(message);
+          gchar *jid  = jidtodisp(lm_message_node_get_attribute(node, "from"));
+          gchar *mesg = g_strdup_printf("Pong: %d second%s %d ms.",
+                                        (int)dsec,
+                                        dsec > 1 ? "s" : "",
+                                        (int)(dusec/1000L));
+
+          scr_WriteIncomingMessage(jid, mesg, 0, HBB_PREFIX_INFO, 0);
+
+          g_free(mesg);
+          g_free(jid);
+        }
+        break;
+
+    case LM_MESSAGE_SUB_TYPE_ERROR:
+        {
+          LmMessageNode *node   = lm_message_get_node(message);
+          const gchar   *from   = lm_message_node_get_attribute(node, "from");
+          const gchar   *type;
+          const gchar   *reason;
+
+          node = lm_message_node_get_child(node, "error");
+          type = lm_message_node_get_attribute(node, "type");
+          if (node->children)
+            reason = node->children->name;
+          else
+            reason = "undefined";
+
+          { // print to buddy's buffer
+            gchar *jid  = jidtodisp(from);
+            gchar *mesg = g_strdup_printf("Ping to %s failed: %s - %s (response time %d second%s %d microseconds)",
+                                          from, type, reason,
+                                          (int)dsec,
+                                          dsec > 1 ? "s" : "",
+                                          (int)(dusec/1000L));
+
+            scr_WriteIncomingMessage(jid, mesg, 0, HBB_PREFIX_INFO, 0);
+
+            g_free(mesg);
+            g_free(jid);
+          }
+        }
+        break;
+
+    default:
+        return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
+        break;
+  }
+
+  return LM_HANDLER_RESULT_REMOVE_MESSAGE;
+}
+
+// Warning!! xmlns has to be a namespace from iq_request_handlers[].xmlns
 void xmpp_iq_request(const char *fulljid, const char *xmlns)
 {
   LmMessage *iq;
   LmMessageNode *query;
   LmMessageHandler *handler;
+  gpointer data = NULL;
+  GDestroyNotify notifier = NULL;
+  GError *error = NULL;
   int i;
 
   iq = lm_message_new_with_sub_type(fulljid, LM_MESSAGE_TYPE_IQ,
@@ -87,11 +165,25 @@
                                     iq_request_handlers[i].querytag,
                                     NULL);
   lm_message_node_set_attribute(query, "xmlns", xmlns);
+
+  if (!g_strcmp0(xmlns, NS_PING)) {     // Create handler for ping queries
+    struct timeval *now = g_new(struct timeval, 1);
+    gettimeofday(now, NULL);
+    data = (gpointer)now;
+    notifier = g_free;
+  }
+
   handler = lm_message_handler_new(iq_request_handlers[i].handler,
-                                   NULL, FALSE);
-  lm_connection_send_with_reply(lconnection, iq, handler, NULL);
+                                   data, notifier);
+
+  lm_connection_send_with_reply(lconnection, iq, handler, &error);
   lm_message_handler_unref(handler);
   lm_message_unref(iq);
+
+  if (error) {
+    scr_LogPrint(LPRINT_LOGNORM, "Error sending IQ request: %s.", error->message);
+    g_error_free(error);
+  }
 }
 
 //  This callback is reached when mcabber receives the first roster update