diff options
Diffstat (limited to 'protocols')
-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[] = |