diff options
| author | Wilmer van der Gaast <wilmer@gaast.net> | 2006-10-08 18:11:16 +0200 | 
|---|---|---|
| committer | Wilmer van der Gaast <wilmer@gaast.net> | 2006-10-08 18:11:16 +0200 | 
| commit | 038d17f834219505cbbdae469b2b150117467dd0 (patch) | |
| tree | ee752d2e307c3e82931337e85d79d23707378f1f /protocols/jabber | |
| parent | 36e9f62a6e6fdb1217b3b819320ac5a94025c448 (diff) | |
Implemented a better node cache using a GLib hash, and preparing to add
event handlers that can be set when sending a packet to handle the reply
to this specific packet. This should allow me to make the iq handler a
lot cleaner.
Diffstat (limited to 'protocols/jabber')
| -rw-r--r-- | protocols/jabber/io.c | 4 | ||||
| -rw-r--r-- | protocols/jabber/iq.c | 4 | ||||
| -rw-r--r-- | protocols/jabber/jabber.c | 63 | ||||
| -rw-r--r-- | protocols/jabber/jabber.h | 16 | ||||
| -rw-r--r-- | protocols/jabber/jabber_util.c | 50 | 
5 files changed, 74 insertions, 63 deletions
| diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 73173dbc..c6ad68e0 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -359,7 +359,7 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data )  		reply = xt_new_node( "bind", NULL, xt_new_node( "resource", set_getstr( &gc->acc->set, "resource" ), NULL ) );  		xt_add_attr( reply, "xmlns", "urn:ietf:params:xml:ns:xmpp-bind" );  		reply = jabber_make_packet( "iq", "set", NULL, reply ); -		jabber_cache_packet( gc, reply ); +		jabber_cache_add( gc, reply );  		if( !jabber_write_packet( gc, reply ) )  			return XT_ABORT; @@ -372,7 +372,7 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data )  		reply = xt_new_node( "session", NULL, NULL );  		xt_add_attr( reply, "xmlns", "urn:ietf:params:xml:ns:xmpp-session" );  		reply = jabber_make_packet( "iq", "set", NULL, reply ); -		jabber_cache_packet( gc, reply ); +		jabber_cache_add( gc, reply );  		if( !jabber_write_packet( gc, reply ) )  			return XT_ABORT; diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 4739d6ab..ae4ed099 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -40,7 +40,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data )  	xmlns = xt_find_attr( query, "xmlns" );  	if( ( s = xt_find_attr( node, "id" ) ) ) -		orig = jabber_packet_from_cache( gc, s ); +		orig = jabber_cache_get( gc, s );  	if( strcmp( type, "result" ) == 0 && xmlns && strcmp( xmlns, "jabber:iq:auth" ) == 0 )  	{ @@ -84,7 +84,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data )  		}  		reply = jabber_make_packet( "iq", "set", NULL, reply ); -		jabber_cache_packet( gc, reply ); +		jabber_cache_add( gc, reply );  		st = jabber_write_packet( gc, reply );  		return st ? XT_HANDLED : XT_ABORT; diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 2c0f7945..32d1d99d 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -78,7 +78,7 @@ static void jabber_login( account_t *acc )  	*jd->server = 0;  	jd->server ++; -	jd->node_cache = xt_new_node( "cache", NULL, NULL ); +	jd->node_cache = g_hash_table_new_full( g_str_hash, g_str_equal, NULL, jabber_cache_entry_free );  	/* Figure out the hostname to connect to. */  	if( acc->server ) @@ -124,7 +124,8 @@ static void jabber_close( struct gaim_connection *gc )  	if( jd->tx_len )  		g_free( jd->txq ); -	xt_free_node( jd->node_cache ); +	g_hash_table_destroy( jd->node_cache ); +	  	xt_free( jd->xt );  	g_free( jd->away_message ); @@ -165,6 +166,18 @@ static GList *jabber_away_states( struct gaim_connection *gc )  	return l;  } +static void jabber_get_info( struct gaim_connection *gc, char *who ) +{ +	struct xt_node *node; +	 +	node = xt_new_node( "query", NULL, NULL ); +	xt_add_attr( node, "xmlns", "http://jabber.org/protocol/disco#info" ); +	node = jabber_make_packet( "iq", "get", who, node ); +	jabber_cache_add( gc, node ); +	 +	jabber_write_packet( gc, node ); +} +  static void jabber_set_away( struct gaim_connection *gc, char *state_txt, char *message )  {  	struct jabber_data *jd = gc->proto_data; @@ -193,50 +206,12 @@ static void jabber_remove_buddy( struct gaim_connection *gc, char *who, char *gr  static void jabber_keepalive( struct gaim_connection *gc )  { -	struct jabber_data *jd = gc->proto_data; -	struct xt_node *c, *tmp; -	  	/* Just any whitespace character is enough as a keepalive for XMPP sessions. */  	jabber_write( gc, "\n", 1 ); -	/* Let's abuse this keepalive for garbage collection of the node cache too. -	   It runs every minute, so let's mark every node with a special flag the -	   first time we see it, and clean it up the second time (clean up all -	   packets with the flag set). -	    -	   node->flags is normally only used by xmltree itself for parsing/handling, -	   so it should be safe to use the variable for gc. */ -	 -	/* This horrible loop is explained in xmltree.c. Makes me wonder if maybe I -	   didn't choose the perfect data structure... */ -	for( c = jd->node_cache->children; c; c =  c->next ) -		if( !( c->flags & XT_SEEN ) ) -			break; -	 -	/* Now c points at the first unflagged node (or at NULL). Clean up -	   everything until that point. */ -	while( jd->node_cache->children != c ) -	{ -		/* -		printf( "Cleaning up:\n" ); -		xt_print( jd->node_cache->children ); -		*/ -		 -		tmp = jd->node_cache->children->next; -		xt_free_node( jd->node_cache->children ); -		jd->node_cache->children = tmp; -	} -	 -	/* Now flag the ones that were still unflagged. */ -	for( c = jd->node_cache->children; c; c = c->next ) -	{ -		/* -		printf( "Flagged:\n" ); -		xt_print( c ); -		*/ -		 -		c->flags |= XT_SEEN; -	} +	/* This runs the garbage collection every minute, which means every packet +	   is in the cache for about a minute (which should be enough AFAIK). */ +	jabber_cache_clean( gc );  }  void jabber_init() @@ -252,7 +227,7 @@ void jabber_init()  //	ret->get_status_string = jabber_get_status_string;  	ret->set_away = jabber_set_away;  //	ret->set_info = jabber_set_info; -//	ret->get_info = jabber_get_info; +	ret->get_info = jabber_get_info;  	ret->add_buddy = jabber_add_buddy;  	ret->remove_buddy = jabber_remove_buddy;  //	ret->chat_send = jabber_chat_send; diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 8ca7d545..58a81810 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -59,7 +59,7 @@ struct jabber_data  	struct jabber_away_state *away_state;  	char *away_message; -	struct xt_node *node_cache; +	GHashTable *node_cache;  };  struct jabber_away_state @@ -68,6 +68,14 @@ struct jabber_away_state  	char *full_name;  }; +typedef xt_status (*jabber_cache_event) ( struct gaim_connection *gc, struct xt_node *packet ); + +struct jabber_cache_entry +{ +	struct xt_node *node; +	jabber_cache_event func; +}; +  /* iq.c */  xt_status jabber_pkt_iq( struct xt_node *node, gpointer data );  int jabber_start_iq_auth( struct gaim_connection *gc ); @@ -87,8 +95,10 @@ int presence_send_request( struct gaim_connection *gc, char *handle, char *reque  char *set_eval_priority( set_t *set, char *value );  char *set_eval_tls( set_t *set, char *value );  struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children ); -void jabber_cache_packet( struct gaim_connection *gc, struct xt_node *node ); -struct xt_node *jabber_packet_from_cache( struct gaim_connection *gc, char *id ); +void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node ); +struct xt_node *jabber_cache_get( struct gaim_connection *gc, char *id ); +void jabber_cache_entry_free( gpointer entry ); +void jabber_cache_clean( struct gaim_connection *gc );  const struct jabber_away_state *jabber_away_state_by_code( char *code );  const struct jabber_away_state *jabber_away_state_by_name( char *name );  void jabber_buddy_ask( struct gaim_connection *gc, char *handle ); diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 845c2d8c..11156258 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -81,30 +81,56 @@ struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_  /* Cache a node/packet for later use. Mainly useful for IQ packets if you need     them when you receive the response. Use this BEFORE sending the packet so     it'll get an id= tag, and do NOT free() the packet after writing it! */ -void jabber_cache_packet( struct gaim_connection *gc, struct xt_node *node ) +void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node )  {  	struct jabber_data *jd = gc->proto_data;  	char *id = g_strdup_printf( "BeeX%04x", next_id++ ); -	 -	/* FIXME: Maybe start using g_error() here if nodes still have a parent, for example? */ +	struct jabber_cache_entry *entry = g_new0( struct jabber_cache_entry, 1 );  	xt_add_attr( node, "id", id ); -	xt_add_child( jd->node_cache, node );  	g_free( id ); +	 +	entry->node = node; +	g_hash_table_insert( jd->node_cache, xt_find_attr( node, "id" ), entry );  } -/* Emptying this cache is a BIG TODO! */ -struct xt_node *jabber_packet_from_cache( struct gaim_connection *gc, char *id ) +struct xt_node *jabber_cache_get( struct gaim_connection *gc, char *id )  {  	struct jabber_data *jd = gc->proto_data; -	struct xt_node *node; -	char *s; +	struct jabber_cache_entry *entry = g_hash_table_lookup( jd->node_cache, id ); -	for( node = jd->node_cache->children; node; node = node->next ) -		if( ( s = xt_find_attr( node, "id" ) ) && strcmp( id, s ) == 0 ) -			break; +	return entry ? entry->node : NULL; +} + +void jabber_cache_entry_free( gpointer data ) +{ +	struct jabber_cache_entry *entry = data; -	return node; +	xt_free_node( entry->node ); +	g_free( entry ); +} + +gboolean jabber_cache_clean_entry( gpointer key, gpointer entry, gpointer nullpointer ); + +void jabber_cache_clean( struct gaim_connection *gc ) +{ +	struct jabber_data *jd = gc->proto_data; +	 +	g_hash_table_foreach_remove( jd->node_cache, jabber_cache_clean_entry, NULL ); +} + +gboolean jabber_cache_clean_entry( gpointer key, gpointer entry_, gpointer nullpointer ) +{ +	struct jabber_cache_entry *entry = entry_; +	struct xt_node *node = entry->node; +	 +	if( node->flags & XT_SEEN ) +		return TRUE; +	else +	{ +		node->flags |= XT_SEEN; +		return FALSE; +	}  }  const struct jabber_away_state jabber_away_state_list[] = | 
