comparison mcabber/mcabber/xmpp_iqrequest.c @ 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 65ba89949252
children a5263e93c5d7
comparison
equal deleted inserted replaced
1704:ab502d645378 1705:ac881b5f9248
20 * USA 20 * USA
21 */ 21 */
22 22
23 #include <string.h> 23 #include <string.h>
24 #include <stdlib.h> 24 #include <stdlib.h>
25 #include <sys/time.h>
25 26
26 #include "xmpp_helper.h" 27 #include "xmpp_helper.h"
27 #include "xmpp_iq.h" 28 #include "xmpp_iq.h"
28 #include "screen.h" 29 #include "screen.h"
29 #include "utils.h" 30 #include "utils.h"
40 LmMessage *m, gpointer user_data); 41 LmMessage *m, gpointer user_data);
41 static LmHandlerResult cb_time(LmMessageHandler *h, LmConnection *c, 42 static LmHandlerResult cb_time(LmMessageHandler *h, LmConnection *c,
42 LmMessage *m, gpointer user_data); 43 LmMessage *m, gpointer user_data);
43 static LmHandlerResult cb_last(LmMessageHandler *h, LmConnection *c, 44 static LmHandlerResult cb_last(LmMessageHandler *h, LmConnection *c,
44 LmMessage *m, gpointer user_data); 45 LmMessage *m, gpointer user_data);
46 static LmHandlerResult cb_ping(LmMessageHandler *h, LmConnection *c,
47 LmMessage *m, gpointer user_data);
45 static LmHandlerResult cb_vcard(LmMessageHandler *h, LmConnection *c, 48 static LmHandlerResult cb_vcard(LmMessageHandler *h, LmConnection *c,
46 LmMessage *m, gpointer user_data); 49 LmMessage *m, gpointer user_data);
47 50
48 static struct IqRequestHandlers 51 static struct IqRequestHandlers
49 { 52 {
53 } iq_request_handlers[] = { 56 } iq_request_handlers[] = {
54 {NS_ROSTER, "query", &cb_roster}, 57 {NS_ROSTER, "query", &cb_roster},
55 {NS_VERSION,"query", &cb_version}, 58 {NS_VERSION,"query", &cb_version},
56 {NS_TIME, "query", &cb_time}, 59 {NS_TIME, "query", &cb_time},
57 {NS_LAST, "query", &cb_last}, 60 {NS_LAST, "query", &cb_last},
61 {NS_PING, "ping", &cb_ping},
58 {NS_VCARD, "vCard", &cb_vcard}, 62 {NS_VCARD, "vCard", &cb_vcard},
59 {NULL, NULL, NULL} 63 {NULL, NULL, NULL}
60 }; 64 };
61 65
62 // Enum for vCard attributes 66 // Enum for vCard attributes
69 vcard_cell = 1<<5, 73 vcard_cell = 1<<5,
70 vcard_inet = 1<<6, 74 vcard_inet = 1<<6,
71 vcard_pref = 1<<7, 75 vcard_pref = 1<<7,
72 }; 76 };
73 77
74 // xmlns has to be a namespace from iq_request_handlers[].xmlns 78 static LmHandlerResult cb_ping(LmMessageHandler *h, LmConnection *c,
79 LmMessage *message, gpointer udata)
80 {
81 struct timeval *timestamp = (struct timeval *) udata;
82 struct timeval now;
83 time_t dsec;
84 suseconds_t dusec;
85
86 gettimeofday(&now, NULL);
87 dsec = now.tv_sec - timestamp->tv_sec;
88 if (now.tv_usec < timestamp->tv_usec) {
89 dusec = now.tv_usec + 1000000 - timestamp->tv_usec;
90 --dsec;
91 } else
92 dusec = now.tv_usec - timestamp->tv_usec;
93
94 switch (lm_message_get_sub_type(message)) {
95 case LM_MESSAGE_SUB_TYPE_RESULT:
96 { // print to buddy's buffer
97 LmMessageNode *node = lm_message_get_node(message);
98 gchar *jid = jidtodisp(lm_message_node_get_attribute(node, "from"));
99 gchar *mesg = g_strdup_printf("Pong: %d second%s %d ms.",
100 (int)dsec,
101 dsec > 1 ? "s" : "",
102 (int)(dusec/1000L));
103
104 scr_WriteIncomingMessage(jid, mesg, 0, HBB_PREFIX_INFO, 0);
105
106 g_free(mesg);
107 g_free(jid);
108 }
109 break;
110
111 case LM_MESSAGE_SUB_TYPE_ERROR:
112 {
113 LmMessageNode *node = lm_message_get_node(message);
114 const gchar *from = lm_message_node_get_attribute(node, "from");
115 const gchar *type;
116 const gchar *reason;
117
118 node = lm_message_node_get_child(node, "error");
119 type = lm_message_node_get_attribute(node, "type");
120 if (node->children)
121 reason = node->children->name;
122 else
123 reason = "undefined";
124
125 { // print to buddy's buffer
126 gchar *jid = jidtodisp(from);
127 gchar *mesg = g_strdup_printf("Ping to %s failed: %s - %s (response time %d second%s %d microseconds)",
128 from, type, reason,
129 (int)dsec,
130 dsec > 1 ? "s" : "",
131 (int)(dusec/1000L));
132
133 scr_WriteIncomingMessage(jid, mesg, 0, HBB_PREFIX_INFO, 0);
134
135 g_free(mesg);
136 g_free(jid);
137 }
138 }
139 break;
140
141 default:
142 return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
143 break;
144 }
145
146 return LM_HANDLER_RESULT_REMOVE_MESSAGE;
147 }
148
149 // Warning!! xmlns has to be a namespace from iq_request_handlers[].xmlns
75 void xmpp_iq_request(const char *fulljid, const char *xmlns) 150 void xmpp_iq_request(const char *fulljid, const char *xmlns)
76 { 151 {
77 LmMessage *iq; 152 LmMessage *iq;
78 LmMessageNode *query; 153 LmMessageNode *query;
79 LmMessageHandler *handler; 154 LmMessageHandler *handler;
155 gpointer data = NULL;
156 GDestroyNotify notifier = NULL;
157 GError *error = NULL;
80 int i; 158 int i;
81 159
82 iq = lm_message_new_with_sub_type(fulljid, LM_MESSAGE_TYPE_IQ, 160 iq = lm_message_new_with_sub_type(fulljid, LM_MESSAGE_TYPE_IQ,
83 LM_MESSAGE_SUB_TYPE_GET); 161 LM_MESSAGE_SUB_TYPE_GET);
84 for (i = 0; strcmp(iq_request_handlers[i].xmlns, xmlns) != 0 ; ++i) 162 for (i = 0; strcmp(iq_request_handlers[i].xmlns, xmlns) != 0 ; ++i)
85 ; 163 ;
86 query = lm_message_node_add_child(iq->node, 164 query = lm_message_node_add_child(iq->node,
87 iq_request_handlers[i].querytag, 165 iq_request_handlers[i].querytag,
88 NULL); 166 NULL);
89 lm_message_node_set_attribute(query, "xmlns", xmlns); 167 lm_message_node_set_attribute(query, "xmlns", xmlns);
168
169 if (!g_strcmp0(xmlns, NS_PING)) { // Create handler for ping queries
170 struct timeval *now = g_new(struct timeval, 1);
171 gettimeofday(now, NULL);
172 data = (gpointer)now;
173 notifier = g_free;
174 }
175
90 handler = lm_message_handler_new(iq_request_handlers[i].handler, 176 handler = lm_message_handler_new(iq_request_handlers[i].handler,
91 NULL, FALSE); 177 data, notifier);
92 lm_connection_send_with_reply(lconnection, iq, handler, NULL); 178
179 lm_connection_send_with_reply(lconnection, iq, handler, &error);
93 lm_message_handler_unref(handler); 180 lm_message_handler_unref(handler);
94 lm_message_unref(iq); 181 lm_message_unref(iq);
182
183 if (error) {
184 scr_LogPrint(LPRINT_LOGNORM, "Error sending IQ request: %s.", error->message);
185 g_error_free(error);
186 }
95 } 187 }
96 188
97 // This callback is reached when mcabber receives the first roster update 189 // This callback is reached when mcabber receives the first roster update
98 // after the connection. 190 // after the connection.
99 static LmHandlerResult cb_roster(LmMessageHandler *h, LmConnection *c, 191 static LmHandlerResult cb_roster(LmMessageHandler *h, LmConnection *c,