disco.c
changeset 60 db0a96df96b5
parent 59 50173578fddc
child 63 d644c08bbc27
equal deleted inserted replaced
59:50173578fddc 60:db0a96df96b5
    60 
    60 
    61 //
    61 //
    62 // private types
    62 // private types
    63 //
    63 //
    64 
    64 
       
    65 #define DISCO_INFO_REQUEST  ( 0 )
       
    66 #define DISCO_ITEMS_REQUEST ( 1 )
       
    67 
    65 // lm message handler userdata
    68 // lm message handler userdata
    66 typedef struct {
    69 typedef struct {
    67 	disco_info_handler_t handler;
    70 	LmMessageHandler *   reply_handler;
    68 	gpointer             data;
    71 	gpointer             data;
    69 	GDestroyNotify       notify;
    72 	GDestroyNotify       notify;
    70 } disco_info_reply_handler_t;
    73 	guint                type;
    71 
    74 	union {
    72 // lm message handler userdata
    75 		disco_info_handler_t  info;
    73 typedef struct {
    76 		disco_items_handler_t items;
    74 	disco_items_handler_t handler;
    77 	} handler;
    75 	gpointer              data;
    78 } disco_request_t;
    76 	GDestroyNotify        notify;
       
    77 } disco_items_reply_handler_t;
       
    78 
    79 
    79 // user request disco handler userdata (common for info and items)
    80 // user request disco handler userdata (common for info and items)
    80 typedef struct {
    81 typedef struct {
    81 	gchar *jid;
    82 	gchar *jid;
    82 	gchar *node;
    83 	gchar *node;
    85 //
    86 //
    86 // globals
    87 // globals
    87 //
    88 //
    88 
    89 
    89 #ifdef MCABBER_API_HAVE_CMD_ID
    90 #ifdef MCABBER_API_HAVE_CMD_ID
    90 static gpointer disco_cmid = NULL;
    91 static gpointer disco_cmid     = NULL;
    91 #endif
    92 #endif
    92 
    93 static guint    disco_cid      = 0;
    93 static guint   disco_cid      = 0;
    94 static guint    disco_hid      = 0;
    94 static guint   disco_hid      = 0;
    95 static GSList * disco_requests = NULL;
    95 static GSList *reply_handlers = NULL;
       
    96 
    96 
    97 //
    97 //
    98 // destroyers
    98 // destroyers
    99 //
    99 //
   100 
   100 
   101 static void disco_info_reply_handler_destroy_notify (gpointer data)
   101 static void disco_request_free ( disco_request_t * cb )
   102 {
   102 {
   103 	disco_info_reply_handler_t *cb = data;
   103 	disco_requests = g_slist_remove ( disco_requests, cb );
   104 	if (cb -> notify)
   104 
   105 		cb -> notify (cb -> data);
   105 	if ( cb -> reply_handler ) {
   106 	g_slice_free (disco_info_reply_handler_t, cb);
   106 		lm_message_handler_invalidate ( cb -> reply_handler );
   107 	return;
   107 #ifdef HAVE_LM_CONNECTION_UNREGISTER_REPLY_HANDLER
   108 }
   108 		if ( lconnection )
   109 
   109 			lm_connection_unregister_reply_handler ( lconnection, cb -> reply_handler );
   110 static void disco_items_reply_handler_destroy_notify (gpointer data)
   110 #endif
   111 {
   111 	}
   112 	disco_items_reply_handler_t *cb = data;
   112 	if ( cb -> notify )
   113 	if (cb -> notify)
   113 		cb -> notify ( cb -> data );
   114 		cb -> notify (cb -> data);
   114 	g_slice_free ( disco_request_t, cb );
   115 	g_slice_free (disco_items_reply_handler_t, cb);
   115 	return;
   116 	return;
   116 }
   117 }
   117 
   118 
   118 static void disco_handler_destroy_notify ( gpointer data )
   119 static void disco_handler_destroy_notify (gpointer data)
   119 {
   120 {
   120 	disco_handler_t * cb = data;
   121 	disco_handler_t *cb = data;
   121 	g_free ( cb -> jid );
   122 	g_free (cb -> jid);
   122 	g_free ( cb -> node );
   123 	g_free (cb -> node);
   123 	g_slice_free ( disco_handler_t, cb );
   124 	g_slice_free (disco_handler_t, cb);
       
   125 	return;
   124 	return;
   126 }
   125 }
   127 
   126 
   128 //
   127 //
   129 // lm reply handlers
   128 // lm reply handlers
   130 //
   129 //
   131 
   130 
   132 static LmHandlerResult disco_info_reply_handler (LmMessageHandler *handler, LmConnection *connection, LmMessage *message, gpointer udata)
   131 static LmHandlerResult disco_reply_handler (LmMessageHandler *handler, LmConnection *connection, LmMessage *message, gpointer udata)
   133 {
   132 {
   134 	disco_info_reply_handler_t *cb = udata;
   133 	disco_request_t * cb     = udata;
   135 
   134 	LmHandlerResult   result = LM_HANDLER_RESULT_REMOVE_MESSAGE;
   136 	reply_handlers = g_slist_remove (reply_handlers, handler);
       
   137 
   135 
   138 	switch (lm_message_get_sub_type (message)) {
   136 	switch (lm_message_get_sub_type (message)) {
   139 	case LM_MESSAGE_SUB_TYPE_RESULT:
   137 	case LM_MESSAGE_SUB_TYPE_RESULT:
   140 
   138 
   141 		{
   139 		{
   142 			LmMessageNode *node       = lm_message_get_node (message);
   140 			LmMessageNode *node = lm_message_get_node (message);
   143 			GSList        *identities = NULL;
       
   144 			GSList        *features   = NULL;
       
   145 
   141 
   146 			node = lm_message_node_get_child (node, "query");
   142 			node = lm_message_node_get_child (node, "query");
   147 
   143 
   148 			// check xmlns
   144 			if ( cb -> type == DISCO_INFO_REQUEST ) {
   149 			if (!node || g_strcmp0 (lm_message_node_get_attribute (node, "xmlns"), NS_DISCO_INFO))
   145 
   150 				break;
   146 				GSList * identities = NULL;
   151 
   147 				GSList * features   = NULL;
   152 			// parse request results
   148 
   153 			if (node->children)
   149 				// check xmlns
   154 				for (node = node->children; node; node = node->next)
   150 				if (!node || g_strcmp0 (lm_message_node_get_attribute (node, "xmlns"), NS_DISCO_INFO))
   155 					if (!strcasecmp (node->name, "identity")) {
   151 					break;
   156 						disco_identity_t *identity = g_slice_new (disco_identity_t);
   152 
   157 
   153 				// parse request results
   158 						identity -> category = lm_message_node_get_attribute (node, "category");
   154 				if (node->children)
   159 						identity -> type     = lm_message_node_get_attribute (node, "type");
   155 					for (node = node->children; node; node = node->next)
   160 						identity -> name     = lm_message_node_get_attribute (node, "name");
   156 						if (!strcasecmp (node->name, "identity")) {
   161 						identity -> reserved = NULL;
   157 							disco_identity_t *identity = g_slice_new (disco_identity_t);
   162 
   158 
   163 						identities = g_slist_append (identities, identity);
   159 							identity -> category = lm_message_node_get_attribute (node, "category");
   164 					} else if (!strcasecmp (node->name, "feature"))
   160 							identity -> type     = lm_message_node_get_attribute (node, "type");
   165 						features = g_slist_insert_sorted (features, (gpointer) lm_message_node_get_attribute (node, "var"), (GCompareFunc) g_strcmp0);
   161 							identity -> name     = lm_message_node_get_attribute (node, "name");
   166 
   162 							identity -> reserved = NULL;
   167 			// call handler
   163 
   168 			cb -> handler (identities, features, cb -> data);
   164 							identities = g_slist_append (identities, identity);
   169 
   165 						} else if (!strcasecmp (node->name, "feature"))
   170 			{ // free resources
   166 							features = g_slist_insert_sorted (features, (gpointer) lm_message_node_get_attribute (node, "var"), (GCompareFunc) g_strcmp0);
   171 				GSList *iel;
   167 
   172 
   168 				// call handler
   173 				for (iel = identities; iel; iel = iel -> next)
   169 				cb -> handler.info (identities, features, cb -> data);
   174 					g_slice_free (disco_identity_t, iel -> data);
   170 
   175 
   171 				{ // free resources
   176 				g_slist_free (identities);
   172 					GSList *iel;
   177 				g_slist_free (features);
   173 
       
   174 					for (iel = identities; iel; iel = iel -> next)
       
   175 						g_slice_free (disco_identity_t, iel -> data);
       
   176 
       
   177 					g_slist_free (identities);
       
   178 					g_slist_free (features);
       
   179 				}
       
   180 
       
   181 			} else { // items request
       
   182 
       
   183 				GSList * items = NULL;
       
   184 
       
   185 				// check xmlns
       
   186 				if (!node || g_strcmp0 (lm_message_node_get_attribute (node, "xmlns"), NS_DISCO_ITEMS))
       
   187 					break;
       
   188 
       
   189 				// parse request results
       
   190 				if (node->children)
       
   191 					for (node = node->children; node; node = node->next)
       
   192 						if (!strcasecmp (node->name, "item")) {
       
   193 							disco_item_t *item = g_slice_new (disco_item_t);
       
   194 
       
   195 							item -> name = lm_message_node_get_attribute (node, "name");
       
   196 							item -> jid  = lm_message_node_get_attribute (node, "jid");
       
   197 							item -> node = lm_message_node_get_attribute (node, "node");
       
   198 
       
   199 							items = g_slist_append (items, item);
       
   200 						}
       
   201 
       
   202 				// call handler
       
   203 				cb -> handler.items (items, cb -> data);
       
   204 
       
   205 				{ // free resources
       
   206 					GSList *iel;
       
   207 
       
   208 					for (iel = items; iel; iel = iel -> next)
       
   209 						g_slice_free (disco_item_t, iel -> data);
       
   210 
       
   211 					g_slist_free (items);
       
   212 				}
   178 			}
   213 			}
   179 		}
   214 		}
   180 
   215 
   181 		break;
   216 		break;
   182 
   217 
   194 				reason = node->children->name;
   229 				reason = node->children->name;
   195 			else
   230 			else
   196 				reason = "undefined";
   231 				reason = "undefined";
   197 
   232 
   198 			// XXX: we need to inform user, but do we really need to print this on every possible error?
   233 			// XXX: we need to inform user, but do we really need to print this on every possible error?
   199 			scr_log_print (LPRINT_LOGNORM, "disco: Service info discovery for %s failed: %s - %s", from, type, reason);
   234 			if ( cb -> type == DISCO_INFO_REQUEST ) {
   200 
   235 
   201 			cb -> handler (NULL, NULL, cb -> data);
   236 				scr_log_print (LPRINT_LOGNORM, "disco: Service info discovery for %s failed: %s - %s", from, type, reason);
       
   237 				cb -> handler.info (NULL, NULL, cb -> data);
       
   238 
       
   239 			} else {
       
   240 
       
   241 				scr_log_print (LPRINT_LOGNORM, "disco: Service items discovery for %s failed: %s - %s", from, type, reason);
       
   242 				cb -> handler.items (NULL, cb -> data);
       
   243 			}
   202 		}
   244 		}
   203 
   245 
   204 		break;
   246 		break;
   205 
   247 
   206 	default:
   248 	default:
   207 		return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
   249 
   208 	}
   250 		result = LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
   209 
       
   210 	return LM_HANDLER_RESULT_REMOVE_MESSAGE;
       
   211 }
       
   212 
       
   213 static LmHandlerResult disco_items_reply_handler (LmMessageHandler *handler, LmConnection *connection, LmMessage *message, gpointer udata)
       
   214 {
       
   215 	disco_items_reply_handler_t *cb = udata;
       
   216 
       
   217 	reply_handlers = g_slist_remove (reply_handlers, handler);
       
   218 
       
   219 	switch (lm_message_get_sub_type (message)) {
       
   220 	case LM_MESSAGE_SUB_TYPE_RESULT:
       
   221 
       
   222 		{
       
   223 			LmMessageNode *node  = lm_message_get_node (message);
       
   224 			GSList        *items = NULL;
       
   225 
       
   226 			node = lm_message_node_get_child (node, "query");
       
   227 
       
   228 			// check xmlns
       
   229 			if (!node || g_strcmp0 (lm_message_node_get_attribute (node, "xmlns"), NS_DISCO_ITEMS))
       
   230 				break;
       
   231 
       
   232 			// parse request results
       
   233 			if (node->children)
       
   234 				for (node = node->children; node; node = node->next)
       
   235 					if (!strcasecmp (node->name, "item")) {
       
   236 						disco_item_t *item = g_slice_new (disco_item_t);
       
   237 
       
   238 						item -> name = lm_message_node_get_attribute (node, "name");
       
   239 						item -> jid  = lm_message_node_get_attribute (node, "jid");
       
   240 						item -> node = lm_message_node_get_attribute (node, "node");
       
   241 
       
   242 						items = g_slist_append (items, item);
       
   243 					}
       
   244 
       
   245 			// call handler
       
   246 			cb -> handler (items, cb -> data);
       
   247 
       
   248 			{ // free resources
       
   249 				GSList *iel;
       
   250 
       
   251 				for (iel = items; iel; iel = iel -> next)
       
   252 					g_slice_free (disco_item_t, iel -> data);
       
   253 
       
   254 				g_slist_free (items);
       
   255 			}
       
   256 		}
       
   257 
   251 
   258 		break;
   252 		break;
   259 
   253 	}
   260 	case LM_MESSAGE_SUB_TYPE_ERROR:
   254 
   261 
   255 	disco_request_free ( cb );
   262 		{
   256 	
   263 			LmMessageNode *node   = lm_message_get_node (message);
   257 	return result;
   264 			const gchar   *from   = lm_message_node_get_attribute (node, "from");
       
   265 			const gchar   *type;
       
   266 			const gchar   *reason;
       
   267 
       
   268 			node = lm_message_node_get_child (node, "error");
       
   269 			type = lm_message_node_get_attribute (node, "type");
       
   270 			if (node->children)
       
   271 				reason = node->children->name;
       
   272 			else
       
   273 				reason = "undefined";
       
   274 
       
   275 			// XXX: we need to inform user, but do we really need to print this on every possible error?
       
   276 			scr_log_print (LPRINT_LOGNORM, "disco: Service items discovery for %s failed: %s - %s", from, type, reason);
       
   277 
       
   278 			cb -> handler (NULL, cb -> data);
       
   279 		}
       
   280 
       
   281 		break;
       
   282 
       
   283 	default:
       
   284 		return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
       
   285 	}
       
   286 
       
   287 	return LM_HANDLER_RESULT_REMOVE_MESSAGE;
       
   288 }
   258 }
   289 
   259 
   290 //
   260 //
   291 // disco requests sending
   261 // disco requests sending
   292 //
   262 //
   302 #endif
   272 #endif
   303 
   273 
   304 gpointer disco_info_request (const gchar *jid, const gchar *dnode, disco_info_handler_t handler, gpointer userdata, GDestroyNotify notify)
   274 gpointer disco_info_request (const gchar *jid, const gchar *dnode, disco_info_handler_t handler, gpointer userdata, GDestroyNotify notify)
   305 {
   275 {
   306 	if (!handler || !xmpp_is_online ()) {
   276 	if (!handler || !xmpp_is_online ()) {
   307 		if (notify)
   277 		if ( handler )
   308 			notify (userdata);
   278 			handler ( NULL, NULL, userdata ); // XXX
       
   279 		if ( notify )
       
   280 			notify ( userdata );
   309 		return NULL;
   281 		return NULL;
   310 	}
   282 	}
   311 
   283 
   312 #if 0
   284 #if 0
   313 	if (0 && !dnode) { // FIXME: no way to get identity(ies) from caps
   285 	if (0 && !dnode) { // FIXME: no way to get identity(ies) from caps
   331 		}
   303 		}
   332 	}
   304 	}
   333 #endif
   305 #endif
   334 
   306 
   335 	{ // send request
   307 	{ // send request
   336 		LmMessage        *request;
   308 		LmMessage *        request;
   337 		LmMessageNode    *node;
   309 		LmMessageNode *    node;
   338 		LmMessageHandler *lhandler;
   310 		LmMessageHandler * lhandler;
   339 		GError           *error    = NULL;
   311 		GError *           error    = NULL;
       
   312 		disco_request_t *  cb       = g_slice_new ( disco_request_t );
   340 
   313 
   341 		request = lm_message_new_with_sub_type (jid, LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_GET);
   314 		request = lm_message_new_with_sub_type (jid, LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_GET);
   342 		node    = lm_message_get_node (request);
   315 		node    = lm_message_get_node (request);
   343 		node    = lm_message_node_add_child (node, "query", NULL);
   316 		node    = lm_message_node_add_child (node, "query", NULL);
   344 		lm_message_node_set_attribute (node, "xmlns", NS_DISCO_INFO);
   317 		lm_message_node_set_attribute (node, "xmlns", NS_DISCO_INFO);
   345 		if (dnode)
   318 		if (dnode)
   346 			lm_message_node_set_attribute (node, "node", dnode);
   319 			lm_message_node_set_attribute (node, "node", dnode);
   347 
   320 
   348 		{
   321 		lhandler = lm_message_handler_new (disco_reply_handler, cb, NULL);
   349 			disco_info_reply_handler_t *cb = g_slice_new (disco_info_reply_handler_t);
   322 
   350 
   323 		cb -> reply_handler = lhandler;
   351 			lhandler = lm_message_handler_new (disco_info_reply_handler, cb, disco_info_reply_handler_destroy_notify);
   324 		cb -> type          = DISCO_INFO_REQUEST;
   352 
   325 		cb -> handler.info  = handler;
   353 			cb -> handler = handler;
   326 		cb -> data          = userdata;
   354 			cb -> data    = userdata;
   327 		cb -> notify        = notify;
   355 			cb -> notify  = notify;
   328 
   356 
   329 		disco_requests = g_slist_append ( disco_requests, cb );
   357 			reply_handlers = g_slist_append (reply_handlers, lhandler);
   330 
   358 
   331 		lm_connection_send_with_reply (lconnection, request, lhandler, &error);
   359 			lm_connection_send_with_reply (lconnection, request, lhandler, &error);
   332 
   360 
   333 		if (error) {
   361 			if (error) {
   334 			scr_log_print (LPRINT_DEBUG, "disco: Error sending disco request: %s.", error -> message);
   362 				// XXX destroy handler and return NULL?
   335 			g_error_free (error);
   363 				scr_log_print (LPRINT_DEBUG, "disco: Error sending disco request: %s.", error -> message);
   336 			handler ( NULL, NULL, userdata ); // XXX
   364 				g_error_free (error);
   337 			disco_request_free ( cb );
   365 			}
   338 			cb = NULL;
   366 
   339 		}
   367 			lm_message_handler_unref (lhandler);
   340 
   368 		}
   341 		lm_message_handler_unref (lhandler);
   369 
       
   370 		lm_message_unref (request);
   342 		lm_message_unref (request);
   371 
   343 
   372 		return lhandler;
   344 		return cb;
   373 	}
   345 	}
   374 }
   346 }
   375 
   347 
   376 gpointer disco_items_request (const gchar *jid, const gchar *dnode, disco_items_handler_t handler, gpointer userdata, GDestroyNotify notify)
   348 gpointer disco_items_request (const gchar *jid, const gchar *dnode, disco_items_handler_t handler, gpointer userdata, GDestroyNotify notify)
   377 {
   349 {
   378 	if (!handler || !xmpp_is_online ()) {
   350 	if (!handler || !xmpp_is_online ()) {
   379 		if (notify)
   351 		if ( handler )
   380 			notify (userdata);
   352 			handler ( NULL, userdata ); // XXX
       
   353 		if ( notify )
       
   354 			notify ( userdata );
   381 		return NULL;
   355 		return NULL;
   382 	}
   356 	}
   383 
   357 
   384 	{ // send request
   358 	{ // send request
   385 		LmMessage        *request;
   359 		LmMessage *        request;
   386 		LmMessageNode    *node;
   360 		LmMessageNode *    node;
   387 		GError           *error    = NULL;
   361 		LmMessageHandler * lhandler;
   388 		LmMessageHandler *lhandler;
   362 		GError *           error    = NULL;
       
   363 		disco_request_t *  cb       = g_slice_new (disco_request_t);
   389 
   364 
   390 		request = lm_message_new_with_sub_type (jid, LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_GET);
   365 		request = lm_message_new_with_sub_type (jid, LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_GET);
   391 		node    = lm_message_get_node (request);
   366 		node    = lm_message_get_node (request);
   392 		node    = lm_message_node_add_child (node, "query", NULL);
   367 		node    = lm_message_node_add_child (node, "query", NULL);
   393 		lm_message_node_set_attribute (node, "xmlns", NS_DISCO_ITEMS);
   368 		lm_message_node_set_attribute (node, "xmlns", NS_DISCO_ITEMS);
   394 		if (dnode)
   369 		if (dnode)
   395 			lm_message_node_set_attribute (node, "node", dnode);
   370 			lm_message_node_set_attribute (node, "node", dnode);
   396 
   371 
   397 		{
   372 		lhandler = lm_message_handler_new (disco_reply_handler, cb, NULL);
   398 			disco_items_reply_handler_t *cb = g_slice_new (disco_items_reply_handler_t);
   373 
   399 
   374 		cb -> reply_handler = lhandler;
   400 			lhandler = lm_message_handler_new (disco_items_reply_handler, cb, disco_items_reply_handler_destroy_notify);
   375 		cb -> type          = DISCO_ITEMS_REQUEST;
   401 
   376 		cb -> handler.items = handler;
   402 			cb -> handler = handler;
   377 		cb -> data          = userdata;
   403 			cb -> data    = userdata;
   378 		cb -> notify        = notify;
   404 			cb -> notify  = notify;
   379 
   405 
   380 		disco_requests = g_slist_append ( disco_requests, cb );
   406 			reply_handlers = g_slist_append (reply_handlers, lhandler);
   381 
   407 
   382 		lm_connection_send_with_reply (lconnection, request, lhandler, &error);
   408 			lm_connection_send_with_reply (lconnection, request, lhandler, &error);
   383 
   409 
   384 		if (error) {
   410 			if (error) {
   385 			scr_log_print (LPRINT_DEBUG, "disco: Error sending disco request: %s.", error -> message);
   411 				// XXX destroy handler and return NULL?
   386 			g_error_free (error);
   412 				scr_log_print (LPRINT_DEBUG, "disco: Error sending disco request: %s.", error -> message);
   387 			handler ( NULL, userdata );
   413 				g_error_free (error);
   388 			disco_request_free ( cb );
   414 			}
   389 			cb = NULL;
   415 
   390 		}
   416 			lm_message_handler_unref (lhandler);
   391 
   417 		}
   392 		lm_message_handler_unref (lhandler);
   418 
       
   419 		lm_message_unref (request);
   393 		lm_message_unref (request);
   420 
   394 
   421 		return lhandler;
   395 		return cb;
   422 	}
   396 	}
   423 }
   397 }
   424 
   398 
   425 void disco_cancel_request (gpointer id)
   399 void disco_cancel_request ( gpointer id )
   426 {
   400 {
   427 	GSList *hel;
   401 	if ( g_slist_find ( disco_requests, id ) ) {
   428 
   402 		disco_request_t * cb = id;
   429 	for (hel = reply_handlers; hel; hel = hel -> next) {
   403 		disco_request_free ( cb );
   430 		if (hel -> data == id) {
       
   431 			LmMessageHandler *handler = id;
       
   432 			reply_handlers = g_slist_remove (reply_handlers, handler);
       
   433 			lm_message_handler_invalidate (handler);
       
   434 #ifdef HAVE_LM_CONNECTION_UNREGISTER_REPLY_HANDLER
       
   435 			if (lconnection)
       
   436 				lm_connection_unregister_reply_handler (lconnection, handler);
       
   437 #endif
       
   438 			return;
       
   439 		}
       
   440 	}
   404 	}
   441 
   405 
   442 	return;
   406 	return;
   443 }
   407 }
   444 
   408 
   618 
   582 
   619 //
   583 //
   620 // module mechanics
   584 // module mechanics
   621 //
   585 //
   622 
   586 
   623 static void disco_unregister_handlers (void)
   587 static void disco_cancel_requests (void)
   624 {
   588 {
   625 	GSList *hel;
   589 	GSList * rel = disco_requests;
   626 
   590 
   627 	for (hel = reply_handlers; hel; hel = hel -> next) {
   591 	while ( rel ) {
   628 		LmMessageHandler *handler = hel -> data;
   592 		disco_request_t * cb = rel -> data;
   629 		lm_message_handler_invalidate (handler);
   593 		rel = rel -> next;
   630 #ifdef HAVE_LM_CONNECTION_UNREGISTER_REPLY_HANDLER
   594 		if ( cb -> type == DISCO_INFO_REQUEST )
   631 		if (lconnection)
   595 			cb -> handler.info ( NULL, NULL, cb -> data );
   632 			lm_connection_unregister_reply_handler (lconnection, handler);
   596 		else
   633 #endif
   597 			cb -> handler.items ( NULL, cb -> data );
   634 	}
   598 		disco_request_free ( cb );
   635 
   599 	}
   636 	g_slist_free (reply_handlers);
       
   637 	reply_handlers = NULL;
       
   638 
   600 
   639 	return;
   601 	return;
   640 }
   602 }
   641 
   603 
   642 static guint disco_hh (const gchar *htype, hk_arg_t *args, gpointer ignore)
   604 static guint disco_hh (const gchar *htype, hk_arg_t *args, gpointer ignore)
   643 {
   605 {
   644 	disco_unregister_handlers ();
   606 	disco_cancel_requests ();
       
   607 	
   645 	return HOOK_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
   608 	return HOOK_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
   646 }
   609 }
   647 
   610 
   648 void disco_init (void)
   611 void disco_init (void)
   649 {
   612 {
   687 
   650 
   688 	// hook handler
   651 	// hook handler
   689 	hk_del_handler (HOOK_PRE_DISCONNECT, disco_hid);
   652 	hk_del_handler (HOOK_PRE_DISCONNECT, disco_hid);
   690 
   653 
   691 	// unregister handlers
   654 	// unregister handlers
   692 	disco_unregister_handlers ();
   655 	disco_cancel_requests ();
   693 
   656 
   694 	return;
   657 	return;
   695 }
   658 }
   696 
   659 
   697 /* vim: se ts=4 sw=4: */
   660 /* vim: se ts=4 sw=4: */