disco.c
changeset 12 4d2ac929e61a
parent 9 ff475b333e44
child 13 339e8bf46039
equal deleted inserted replaced
11:18de00544c46 12:4d2ac929e61a
    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: */