20 */ |
20 */ |
21 |
21 |
22 #include <glib.h> |
22 #include <glib.h> |
23 #include <gmodule.h> |
23 #include <gmodule.h> |
24 #include <loudmouth/loudmouth.h> |
24 #include <loudmouth/loudmouth.h> |
25 #include <strings.h> |
25 #include <string.h> |
26 |
26 |
27 #include "commands.h" |
27 #include "commands.h" |
28 #include "logprint.h" |
28 #include "logprint.h" |
29 #include "utils.h" |
29 #include "utils.h" |
30 #include "xmpp.h" |
30 #include "xmpp.h" |
31 #include "compl.h" |
31 #include "compl.h" |
32 #include "xmpp_defines.h" |
32 #include "xmpp_defines.h" |
33 #include "screen.h" |
33 #include "screen.h" |
34 #include "hbuf.h" |
34 #include "hbuf.h" |
35 #include "hooks.h" |
35 |
36 |
36 static guint disco_cid = 0; |
37 static GSList *reply_handlers = NULL; |
37 static LmMessageHandler *disco_info_reply_handler = NULL; |
38 static guint disco_cid = 0; |
38 static LmMessageHandler *disco_items_reply_handler = NULL; |
39 |
39 |
40 static LmHandlerResult disco_handler (LmMessageHandler *handler, LmConnection *connection, LmMessage *message, gpointer udata) |
40 static LmHandlerResult disco_handler (LmMessage *message, gboolean info_request) |
41 { |
41 { |
42 int info_request = (int) udata; |
|
43 |
|
44 reply_handlers = g_slist_remove (reply_handlers, handler); |
|
45 |
|
46 switch (lm_message_get_sub_type (message)) { |
42 switch (lm_message_get_sub_type (message)) { |
47 case LM_MESSAGE_SUB_TYPE_RESULT: |
43 case LM_MESSAGE_SUB_TYPE_RESULT: |
48 |
44 |
49 { |
45 { |
50 LmMessageNode *node = lm_message_get_node (message); |
46 LmMessageNode *node = lm_message_get_node (message); |
161 } |
157 } |
162 |
158 |
163 return LM_HANDLER_RESULT_REMOVE_MESSAGE; |
159 return LM_HANDLER_RESULT_REMOVE_MESSAGE; |
164 } |
160 } |
165 |
161 |
|
162 static LmHandlerResult disco_info_handler (LmMessageHandler *handler, LmConnection *connection, LmMessage *message, gpointer udata) |
|
163 { |
|
164 return disco_handler (message, TRUE); |
|
165 } |
|
166 |
|
167 static LmHandlerResult disco_items_handler (LmMessageHandler *handler, LmConnection *connection, LmMessage *message, gpointer udata) |
|
168 { |
|
169 return disco_handler (message, FALSE); |
|
170 } |
|
171 |
166 static void do_disco (char *arg) |
172 static void do_disco (char *arg) |
167 { |
173 { |
168 char **args = split_arg (arg, 3, 0); |
174 char **args = split_arg (arg, 3, 0); |
169 int info = -1; |
175 int info = -1; |
170 |
176 |
195 if (args[2]) |
201 if (args[2]) |
196 dnode = to_utf8 (args[2]); |
202 dnode = to_utf8 (args[2]); |
197 } |
203 } |
198 // XXX send to all resources/current resource? |
204 // XXX send to all resources/current resource? |
199 |
205 |
200 handler = lm_message_handler_new (disco_handler, (gpointer) info, NULL); |
|
201 |
|
202 reply_handlers = g_slist_append (reply_handlers, handler); |
|
203 |
|
204 { // create message |
206 { // create message |
205 LmMessageNode *node; |
207 LmMessageNode *node; |
206 |
208 |
207 request = lm_message_new_with_sub_type (to ? to : CURRENT_JID, LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_GET); |
209 request = lm_message_new_with_sub_type (to ? to : CURRENT_JID, LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_GET); |
208 node = lm_message_get_node (request); |
210 node = lm_message_get_node (request); |
210 lm_message_node_set_attribute (node, "xmlns", info ? NS_DISCO_INFO : NS_DISCO_ITEMS); |
212 lm_message_node_set_attribute (node, "xmlns", info ? NS_DISCO_INFO : NS_DISCO_ITEMS); |
211 if (dnode) |
213 if (dnode) |
212 lm_message_node_set_attribute (node, "node", dnode); |
214 lm_message_node_set_attribute (node, "node", dnode); |
213 } |
215 } |
214 |
216 |
215 lm_connection_send_with_reply (lconnection, request, handler, NULL); |
217 lm_connection_send_with_reply (lconnection, request, info ? disco_info_reply_handler : disco_items_reply_handler, NULL); |
216 |
218 |
217 lm_message_handler_unref (handler); |
|
218 lm_message_unref (request); |
219 lm_message_unref (request); |
219 g_free (dnode); |
220 if (dnode) |
|
221 g_free (dnode); |
220 g_free (to); |
222 g_free (to); |
221 } |
223 } |
222 |
224 |
223 free_arg_lst (args); |
225 free_arg_lst (args); |
224 } |
226 } |
225 |
227 |
226 static void disco_free_reply_handlers (void) |
|
227 { |
|
228 GSList *hel; |
|
229 |
|
230 // let's hope, that after invalidation, lm will remove and free unreffed by us handler |
|
231 for (hel = reply_handlers; hel; hel = hel->next) { |
|
232 LmMessageHandler *handler = (LmMessageHandler *) hel->data; |
|
233 lm_message_handler_invalidate (handler); |
|
234 } |
|
235 |
|
236 g_slist_free (reply_handlers); |
|
237 reply_handlers = NULL; |
|
238 } |
|
239 |
|
240 // release handlers before reconnect |
|
241 static void disco_hh (guint32 hid, hk_arg_t *args, gpointer userdata) |
|
242 { |
|
243 hk_arg_t *arg; |
|
244 |
|
245 for (arg = args; arg->name; arg++) { |
|
246 if (!strcmp (arg->name, "hook") && !strcmp (arg->value, "hook-pre-disconnect")) { |
|
247 disco_free_reply_handlers (); |
|
248 return; |
|
249 } |
|
250 } |
|
251 } |
|
252 |
|
253 const gchar *g_module_check_init(GModule *module) |
228 const gchar *g_module_check_init(GModule *module) |
254 { |
229 { |
255 reply_handlers = NULL; |
230 // create handlers |
|
231 disco_info_reply_handler = lm_message_handler_new (disco_info_handler, NULL, NULL); |
|
232 disco_items_reply_handler = lm_message_handler_new (disco_items_handler, NULL, NULL); |
256 |
233 |
257 // completion |
234 // completion |
258 disco_cid = compl_new_category (); |
235 disco_cid = compl_new_category (); |
259 if (disco_cid) { |
236 if (disco_cid) { |
260 compl_add_category_word (disco_cid, "info"); |
237 compl_add_category_word (disco_cid, "info"); |
262 } |
239 } |
263 |
240 |
264 // command |
241 // command |
265 cmd_add ("disco", "", disco_cid, COMPL_JID, do_disco, NULL); |
242 cmd_add ("disco", "", disco_cid, COMPL_JID, do_disco, NULL); |
266 |
243 |
267 // register hook handler |
|
268 hk_add_handler (disco_hh, HOOK_INTERNAL, NULL); |
|
269 |
|
270 return NULL; |
244 return NULL; |
271 } |
245 } |
272 |
246 |
273 void g_module_unload(GModule *module) |
247 void g_module_unload(GModule *module) |
274 { |
248 { |
275 // release handlers |
|
276 disco_free_reply_handlers (); |
|
277 |
|
278 // remove hook handler |
|
279 hk_del_handler (disco_hh, NULL); |
|
280 |
|
281 // command |
249 // command |
282 cmd_del ("disco"); |
250 cmd_del ("disco"); |
283 |
251 |
284 // completion |
252 // completion |
285 if (disco_cid) |
253 if (disco_cid) |
286 compl_del_category (disco_cid); |
254 compl_del_category (disco_cid); |
287 } |
255 |
288 |
256 // unregister handlers |
289 /* vim: se ts=4: */ |
257 if (disco_info_reply_handler) { |
|
258 lm_message_handler_invalidate (disco_info_reply_handler); |
|
259 lm_message_handler_unref (disco_info_reply_handler); |
|
260 } |
|
261 |
|
262 if (disco_items_reply_handler) { |
|
263 lm_message_handler_invalidate (disco_items_reply_handler); |
|
264 lm_message_handler_unref (disco_items_reply_handler); |
|
265 } |
|
266 } |
|
267 |
|
268 /* vim: se ts=4 sw=4: */ |