aboutsummaryrefslogtreecommitdiffstats
path: root/protocols
diff options
context:
space:
mode:
Diffstat (limited to 'protocols')
-rw-r--r--protocols/jabber/io.c4
-rw-r--r--protocols/jabber/iq.c4
-rw-r--r--protocols/jabber/jabber.c63
-rw-r--r--protocols/jabber/jabber.h16
-rw-r--r--protocols/jabber/jabber_util.c50
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[] =