diff options
author | Wilmer van der Gaast <wilmer@gaast.net> | 2010-03-18 14:38:06 +0000 |
---|---|---|
committer | Wilmer van der Gaast <wilmer@gaast.net> | 2010-03-18 14:38:06 +0000 |
commit | 638feab58aebc97d646820dd1bc9b8d9fbeec29d (patch) | |
tree | c4022afb6ffef2b672f3aaf16c8bd7a9f7b23ea8 /protocols/jabber/jabber_util.c | |
parent | 6ce01bec119c96243a8d43e28681cc512fbd0950 (diff) | |
parent | 842cd8dbfb98b61af33b5fe481364c3cfbeaca04 (diff) |
Merging in Jabber resource selection fix. This adds the activity_timeout
setting, which makes BitlBee send a message to bare JIDs if there was no
recent seen activity from any of the person's resources. This should fix
most issues with messages going to the wrong resource (i.e. someone's
mobile phone instead of something more sensible).
Diffstat (limited to 'protocols/jabber/jabber_util.c')
-rw-r--r-- | protocols/jabber/jabber_util.c | 75 |
1 files changed, 43 insertions, 32 deletions
diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 185d3878..db5944bc 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -3,7 +3,7 @@ * BitlBee - An IRC to IM gateway * * Jabber module - Misc. stuff * * * -* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net> * +* Copyright 2006-2010 Wilmer van der Gaast <wilmer@gaast.net> * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -344,6 +344,11 @@ struct jabber_buddy *jabber_buddy_add( struct im_connection *ic, char *full_jid_ if( ( bud = g_hash_table_lookup( jd->buddies, full_jid ) ) ) { + /* The first entry is always a bare JID. If there are more, we + should ignore the first one here. */ + if( bud->next ) + bud = bud->next; + /* If this is a transport buddy or whatever, it can't have more than one instance, so this is always wrong: */ if( s == NULL || bud->resource == NULL ) @@ -378,10 +383,15 @@ struct jabber_buddy *jabber_buddy_add( struct im_connection *ic, char *full_jid_ } else { - /* Keep in mind that full_jid currently isn't really - a full JID... */ - new->bare_jid = g_strdup( full_jid ); + new->full_jid = new->bare_jid = g_strdup( full_jid ); g_hash_table_insert( jd->buddies, new->bare_jid, new ); + + if( s ) + { + new->next = g_new0( struct jabber_buddy, 1 ); + new->next->bare_jid = new->bare_jid; + new = new->next; + } } if( s ) @@ -407,7 +417,7 @@ struct jabber_buddy *jabber_buddy_add( struct im_connection *ic, char *full_jid_ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_, get_buddy_flags_t flags ) { struct jabber_data *jd = ic->proto_data; - struct jabber_buddy *bud; + struct jabber_buddy *bud, *head; char *s, *jid; jid = jabber_normalize( jid_ ); @@ -419,6 +429,11 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_, *s = 0; if( ( bud = g_hash_table_lookup( jd->buddies, jid ) ) ) { + bare_exists = 1; + + if( bud->next ) + bud = bud->next; + /* Just return the first one for this bare JID. */ if( flags & GET_BUDDY_FIRST ) { @@ -440,16 +455,9 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_, if( strcmp( bud->resource, s + 1 ) == 0 ) break; } - else - { - /* This variable tells the if down here that the bare - JID already exists and we should feel free to add - more resources, if the caller asked for that. */ - bare_exists = 1; - } if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && - ( !bare_exists || imcb_find_buddy( ic, jid ) ) ) + ( bare_exists || imcb_find_buddy( ic, jid ) ) ) { *s = '/'; bud = jabber_buddy_add( ic, jid ); @@ -463,7 +471,8 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_, struct jabber_buddy *best_prio, *best_time; char *set; - bud = g_hash_table_lookup( jd->buddies, jid ); + head = g_hash_table_lookup( jd->buddies, jid ); + bud = ( head && head->next ) ? head->next : head; g_free( jid ); @@ -480,22 +489,31 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_, else if( flags & GET_BUDDY_FIRST ) /* Looks like the caller doesn't care about details. */ return bud; + else if( flags & GET_BUDDY_BARE ) + return head; best_prio = best_time = bud; for( ; bud; bud = bud->next ) { if( bud->priority > best_prio->priority ) best_prio = bud; - if( bud->last_act > best_time->last_act ) + if( bud->last_msg > best_time->last_msg ) best_time = bud; } if( ( set = set_getstr( &ic->acc->set, "resource_select" ) ) == NULL ) return NULL; - else if( strcmp( set, "activity" ) == 0 ) - return best_time; - else /* if( strcmp( set, "priority" ) == 0 ) */ + else if( strcmp( set, "priority" ) == 0 ) return best_prio; + else if( flags & GET_BUDDY_BARE_OK ) /* && strcmp( set, "activity" ) == 0 */ + { + if( best_time->last_msg + set_getint( &ic->acc->set, "activity_timeout" ) >= time( NULL ) ) + return best_time; + else + return head; + } + else + return best_time; } } @@ -537,7 +555,7 @@ struct jabber_buddy *jabber_buddy_by_ext_jid( struct im_connection *ic, char *ji int jabber_buddy_remove( struct im_connection *ic, char *full_jid_ ) { struct jabber_data *jd = ic->proto_data; - struct jabber_buddy *bud, *prev, *bi; + struct jabber_buddy *bud, *prev = NULL, *bi; char *s, *full_jid; full_jid = jabber_normalize( full_jid_ ); @@ -547,6 +565,9 @@ int jabber_buddy_remove( struct im_connection *ic, char *full_jid_ ) if( ( bud = g_hash_table_lookup( jd->buddies, full_jid ) ) ) { + if( bud->next ) + bud = (prev=bud)->next; + /* If there's only one item in the list (and if the resource matches), removing it is simple. (And the hash reference should be removed too!) */ @@ -554,16 +575,7 @@ int jabber_buddy_remove( struct im_connection *ic, char *full_jid_ ) ( ( s == NULL && bud->resource == NULL ) || ( bud->resource && s && strcmp( bud->resource, s + 1 ) == 0 ) ) ) { - g_hash_table_remove( jd->buddies, bud->bare_jid ); - g_free( bud->bare_jid ); - g_free( bud->ext_jid ); - g_free( bud->full_jid ); - g_free( bud->away_message ); - g_free( bud ); - - g_free( full_jid ); - - return 1; + return jabber_buddy_remove_bare( ic, full_jid ); } else if( s == NULL || bud->resource == NULL ) { @@ -574,7 +586,7 @@ int jabber_buddy_remove( struct im_connection *ic, char *full_jid_ ) } else { - for( bi = bud, prev = NULL; bi; bi = (prev=bi)->next ) + for( bi = bud; bi; bi = (prev=bi)->next ) if( strcmp( bi->resource, s + 1 ) == 0 ) break; @@ -585,8 +597,7 @@ int jabber_buddy_remove( struct im_connection *ic, char *full_jid_ ) if( prev ) prev->next = bi->next; else - /* The hash table should point at the second - item, because we're removing the first. */ + /* Don't think this should ever happen anymore. */ g_hash_table_replace( jd->buddies, bi->bare_jid, bi->next ); g_free( bi->ext_jid ); |