# HG changeset patch # User Mikael Berthe # Date 1265660585 -3600 # Node ID ac881b5f9248590ebbf043c78bc70d26abc10558 # Parent ab502d6453780b88469d3041fa4a7d2ddb6b8668 Add /request ping (XEP-0199), by merging isbear's module diff -r ab502d645378 -r ac881b5f9248 mcabber/mcabber/commands.c --- 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: diff -r ab502d645378 -r ac881b5f9248 mcabber/mcabber/xmpp.c --- 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; diff -r ab502d645378 -r ac881b5f9248 mcabber/mcabber/xmpp.h --- 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 { diff -r ab502d645378 -r ac881b5f9248 mcabber/mcabber/xmpp_iqrequest.c --- 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 #include +#include #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