Changeset 861c199


Ignore:
Timestamp:
2006-10-08T18:41:11Z (14 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Branches:
master
Children:
6a1128d
Parents:
038d17f
Message:

Moved handling of all IQ packets to event handlers. Cleaned up a LOT of
mess in iq.c!

Location:
protocols/jabber
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • protocols/jabber/io.c

    r038d17f r861c199  
    214214                                        else
    215215                                        {
    216                                                 return jabber_start_iq_auth( gc );
     216                                                return jabber_init_iq_auth( gc );
    217217                                        }
    218218                                }
     
    351351        else if( !( jd->flags & JFLAG_AUTHENTICATED ) && sasl_supported( gc ) )
    352352        {
    353                 if( !jabber_start_iq_auth( gc ) )
     353                if( !jabber_init_iq_auth( gc ) )
    354354                        return XT_ABORT;
    355355        }
     
    360360                xt_add_attr( reply, "xmlns", "urn:ietf:params:xml:ns:xmpp-bind" );
    361361                reply = jabber_make_packet( "iq", "set", NULL, reply );
    362                 jabber_cache_add( gc, reply );
     362                jabber_cache_add( gc, reply, jabber_pkt_bind_sess );
    363363               
    364364                if( !jabber_write_packet( gc, reply ) )
     
    373373                xt_add_attr( reply, "xmlns", "urn:ietf:params:xml:ns:xmpp-session" );
    374374                reply = jabber_make_packet( "iq", "set", NULL, reply );
    375                 jabber_cache_add( gc, reply );
     375                jabber_cache_add( gc, reply, jabber_pkt_bind_sess );
    376376               
    377377                if( !jabber_write_packet( gc, reply ) )
  • protocols/jabber/iq.c

    r038d17f r861c199  
    2828        struct gaim_connection *gc = data;
    2929        struct jabber_data *jd = gc->proto_data;
    30         struct xt_node *query, *reply = NULL, *orig = NULL, *c;
    31         char *s, *type, *xmlns;
    32         int st;
    33        
    34         query = xt_find_node( node->children, "query" );
     30        char *type, *s;
     31       
    3532        type = xt_find_attr( node, "type" );
    3633       
    3734        if( !type )
    38                 return XT_HANDLED;      /* Ignore it for now, don't know what's best... */
    39        
    40         xmlns = xt_find_attr( query, "xmlns" );
    41        
    42         if( ( s = xt_find_attr( node, "id" ) ) )
    43                 orig = jabber_cache_get( gc, s );
    44        
    45         if( strcmp( type, "result" ) == 0 && xmlns && strcmp( xmlns, "jabber:iq:auth" ) == 0 )
    46         {
    47                 /* Time to authenticate ourselves! */
    48                 reply = xt_new_node( "query", NULL, NULL );
    49                 xt_add_attr( reply, "xmlns", "jabber:iq:auth" );
    50                 xt_add_child( reply, xt_new_node( "username", jd->username, NULL ) );
    51                 xt_add_child( reply, xt_new_node( "resource", set_getstr( &gc->acc->set, "resource" ), NULL ) );
    52                
    53                 if( xt_find_node( query->children, "digest" ) && ( s = xt_find_attr( jd->xt->root, "id" ) ) )
    54                 {
    55                         /* We can do digest authentication, it seems, and of
    56                            course we prefer that. */
    57                         SHA_CTX sha;
    58                         char hash_hex[40];
    59                         unsigned char hash[20];
    60                         int i;
    61                        
    62                         shaInit( &sha );
    63                         shaUpdate( &sha, (unsigned char*) s, strlen( s ) );
    64                         shaUpdate( &sha, (unsigned char*) gc->acc->pass, strlen( gc->acc->pass ) );
    65                         shaFinal( &sha, hash );
    66                        
    67                         for( i = 0; i < 20; i ++ )
    68                                 sprintf( hash_hex + i * 2, "%02x", hash[i] );
    69                        
    70                         xt_add_child( reply, xt_new_node( "digest", hash_hex, NULL ) );
    71                 }
    72                 else if( xt_find_node( query->children, "password" ) )
    73                 {
    74                         /* We'll have to stick with plaintext. Let's hope we're using SSL/TLS... */
    75                         xt_add_child( reply, xt_new_node( "password", gc->acc->pass, NULL ) );
    76                 }
    77                 else
    78                 {
    79                         xt_free_node( reply );
    80                        
    81                         hide_login_progress( gc, "Can't find suitable authentication method" );
    82                         signoff( gc );
    83                         return XT_ABORT;
    84                 }
    85                
    86                 reply = jabber_make_packet( "iq", "set", NULL, reply );
    87                 jabber_cache_add( gc, reply );
    88                 st = jabber_write_packet( gc, reply );
    89                
    90                 return st ? XT_HANDLED : XT_ABORT;
    91         }
    92         if( strcmp( type, "result" ) == 0 && xmlns && strcmp( xmlns, "jabber:iq:roster" ) == 0 )
    93         {
    94                 struct xt_node *node;
    95                
    96                 node = query->children;
    97                 while( ( node = xt_find_node( node, "item" ) ) )
    98                 {
    99                         char *jid = xt_find_attr( node, "jid" );
    100                         char *name = xt_find_attr( node, "name" );
    101                         char *sub = xt_find_attr( node, "subscription" );
    102                        
    103                         if( jid && sub && ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) )
    104                                 add_buddy( gc, NULL, jid, name );
    105                        
    106                         node = node->next;
    107                 }
    108                
    109                 account_online( gc );
    110         }
    111         else if( strcmp( type, "result" ) == 0 && orig )
    112         {
    113                 struct xt_node *c;
    114                
    115                 if( !( jd->flags & JFLAG_AUTHENTICATED ) &&
    116                     ( c = xt_find_node( orig->children, "query" ) ) &&
    117                     ( c = xt_find_node( c->children, "username" ) ) &&
    118                     c->text_len )
    119                 {
    120                         /* This happens when we just successfully authenticated
    121                            the old (non-SASL) way. */
    122                         jd->flags |= JFLAG_AUTHENTICATED;
    123                         if( !jabber_get_roster( gc ) )
    124                                 return XT_ABORT;
    125                 }
    126                 /* Tricky: Look for <bind> in the reply, because the server
    127                    should confirm the chosen resource string there. For
    128                    <session>, however, look in the cache, because the server
    129                    will probably not include it in its reply. */
    130                 else if( ( c = xt_find_node( node->children, "bind" ) ) ||
    131                          ( c = xt_find_node( orig->children, "session" ) ) )
    132                 {
    133                         if( strcmp( c->name, "bind" ) == 0 )
    134                         {
    135                                 c = xt_find_node( c->children, "jid" );
    136                                 if( c && c->text_len && ( s = strchr( c->text, '/' ) ) &&
    137                                     strcmp( s + 1, set_getstr( &gc->acc->set, "resource" ) ) != 0 )
    138                                         serv_got_crap( gc, "Server changed session resource string to `%s'", s + 1 );
    139                                
    140                                 jd->flags &= ~JFLAG_WAIT_BIND;
    141                         }
    142                         else if( strcmp( c->name, "session" ) == 0 )
    143                                 jd->flags &= ~JFLAG_WAIT_SESSION;
    144                        
    145                         if( ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 )
    146                         {
    147                                 if( !jabber_get_roster( gc ) )
    148                                         return XT_ABORT;
    149                         }
    150                 }
    151         }
    152         else if( strcmp( type, "error" ) == 0 )
    153         {
    154                 if( !( jd->flags & JFLAG_AUTHENTICATED ) &&
    155                       orig &&
    156                     ( c = xt_find_node( orig->children, "query" ) ) &&
    157                     ( c = xt_find_node( c->children, "username" ) ) &&
    158                     c->text_len )
    159                 {
    160                         hide_login_progress( gc, "Authentication failure" );
    161                         signoff( gc );
    162                         return XT_ABORT;
    163                 }
    164         }
    165        
    166         return XT_HANDLED;
    167 }
    168 
    169 int jabber_start_iq_auth( struct gaim_connection *gc )
     35        {
     36                hide_login_progress_error( gc, "Received IQ packet without type!" );
     37                signoff( gc );
     38                return XT_ABORT;
     39        }
     40       
     41        if( ( s = xt_find_attr( node, "id" ) ) &&
     42            ( strcmp( type, "result" ) == 0 || strcmp( type, "error" ) == 0 ) )
     43        {
     44                struct jabber_cache_entry *entry;
     45               
     46                entry = g_hash_table_lookup( jd->node_cache, s );
     47               
     48                if( entry == NULL )
     49                        serv_got_crap( gc, "WARNING: Received IQ %s packet with unknown/expired ID %s!", type, s );
     50                else if( entry->func )
     51                        return entry->func( gc, node, entry->node );
     52        }
     53       
     54        return XT_HANDLED;
     55}
     56
     57static xt_status jabber_do_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig );
     58static xt_status jabber_finish_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig );
     59
     60int jabber_init_iq_auth( struct gaim_connection *gc )
    17061{
    17162        struct jabber_data *jd = gc->proto_data;
     
    17768        node = jabber_make_packet( "iq", "get", NULL, node );
    17869       
    179         st = jabber_write_packet( gc, node );
    180        
    181         xt_free_node( node );
    182         return st;
    183 }
     70        jabber_cache_add( gc, node, jabber_do_iq_auth );
     71        st = jabber_write_packet( gc, node );
     72       
     73        return st;
     74}
     75
     76static xt_status jabber_do_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig )
     77{
     78        struct jabber_data *jd = gc->proto_data;
     79        struct xt_node *reply, *query;
     80        xt_status st;
     81        char *s;
     82       
     83        query = xt_find_node( node->children, "query" );
     84       
     85        /* Time to authenticate ourselves! */
     86        reply = xt_new_node( "query", NULL, NULL );
     87        xt_add_attr( reply, "xmlns", "jabber:iq:auth" );
     88        xt_add_child( reply, xt_new_node( "username", jd->username, NULL ) );
     89        xt_add_child( reply, xt_new_node( "resource", set_getstr( &gc->acc->set, "resource" ), NULL ) );
     90       
     91        if( xt_find_node( query->children, "digest" ) && ( s = xt_find_attr( jd->xt->root, "id" ) ) )
     92        {
     93                /* We can do digest authentication, it seems, and of
     94                   course we prefer that. */
     95                SHA_CTX sha;
     96                char hash_hex[40];
     97                unsigned char hash[20];
     98                int i;
     99               
     100                shaInit( &sha );
     101                shaUpdate( &sha, (unsigned char*) s, strlen( s ) );
     102                shaUpdate( &sha, (unsigned char*) gc->acc->pass, strlen( gc->acc->pass ) );
     103                shaFinal( &sha, hash );
     104               
     105                for( i = 0; i < 20; i ++ )
     106                        sprintf( hash_hex + i * 2, "%02x", hash[i] );
     107               
     108                xt_add_child( reply, xt_new_node( "digest", hash_hex, NULL ) );
     109        }
     110        else if( xt_find_node( query->children, "password" ) )
     111        {
     112                /* We'll have to stick with plaintext. Let's hope we're using SSL/TLS... */
     113                xt_add_child( reply, xt_new_node( "password", gc->acc->pass, NULL ) );
     114        }
     115        else
     116        {
     117                xt_free_node( reply );
     118               
     119                hide_login_progress( gc, "Can't find suitable authentication method" );
     120                signoff( gc );
     121                return XT_ABORT;
     122        }
     123       
     124        reply = jabber_make_packet( "iq", "set", NULL, reply );
     125        jabber_cache_add( gc, reply, jabber_finish_iq_auth );
     126        st = jabber_write_packet( gc, reply );
     127       
     128        return st ? XT_HANDLED : XT_ABORT;
     129}
     130
     131static xt_status jabber_finish_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig )
     132{
     133        char *type = xt_find_attr( node, "type" );
     134        struct jabber_data *jd = gc->proto_data;
     135       
     136        if( strcmp( type, "error" ) == 0 )
     137        {
     138                hide_login_progress( gc, "Authentication failure" );
     139                signoff( gc );
     140                return XT_ABORT;
     141        }
     142        else if( strcmp( type, "result" ) == 0 )
     143        {
     144                /* This happens when we just successfully authenticated the
     145                   old (non-SASL) way. */
     146                jd->flags |= JFLAG_AUTHENTICATED;
     147                if( !jabber_get_roster( gc ) )
     148                        return XT_ABORT;
     149        }
     150       
     151        return XT_HANDLED;
     152}
     153
     154xt_status jabber_pkt_bind_sess( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig )
     155{
     156        struct jabber_data *jd = gc->proto_data;
     157        struct xt_node *c;
     158        char *s;
     159       
     160        if( ( c = xt_find_node( node->children, "bind" ) ) )
     161        {
     162                c = xt_find_node( c->children, "jid" );
     163                if( c && c->text_len && ( s = strchr( c->text, '/' ) ) &&
     164                    strcmp( s + 1, set_getstr( &gc->acc->set, "resource" ) ) != 0 )
     165                        serv_got_crap( gc, "Server changed session resource string to `%s'", s + 1 );
     166               
     167                jd->flags &= ~JFLAG_WAIT_BIND;
     168        }
     169        else
     170        {
     171                jd->flags &= ~JFLAG_WAIT_SESSION;
     172        }
     173       
     174        if( ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 )
     175        {
     176                if( !jabber_get_roster( gc ) )
     177                        return XT_ABORT;
     178        }
     179       
     180        return XT_HANDLED;
     181}
     182
     183static xt_status jabber_parse_roster( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig );
    184184
    185185int jabber_get_roster( struct gaim_connection *gc )
     
    194194        node = jabber_make_packet( "iq", "get", NULL, node );
    195195       
    196         st = jabber_write_packet( gc, node );
    197        
    198         xt_free_node( node );
    199         return st;
     196        jabber_cache_add( gc, node, jabber_parse_roster );
     197        st = jabber_write_packet( gc, node );
     198       
     199        return st;
     200}
     201
     202static xt_status jabber_parse_roster( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig )
     203{
     204        struct xt_node *query, *c;
     205       
     206        query = xt_find_node( node->children, "query" );
     207       
     208        c = query->children;
     209        while( ( c = xt_find_node( c, "item" ) ) )
     210        {
     211                char *jid = xt_find_attr( c, "jid" );
     212                char *name = xt_find_attr( c, "name" );
     213                char *sub = xt_find_attr( c, "subscription" );
     214               
     215                if( jid && sub && ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) )
     216                        add_buddy( gc, NULL, jid, name );
     217               
     218                c = c->next;
     219        }
     220       
     221        account_online( gc );
     222       
     223        return XT_HANDLED;
    200224}
    201225
  • protocols/jabber/jabber.c

    r038d17f r861c199  
    174174        xt_add_attr( node, "xmlns", "http://jabber.org/protocol/disco#info" );
    175175        node = jabber_make_packet( "iq", "get", who, node );
    176         jabber_cache_add( gc, node );
     176        // jabber_cache_add( gc, node, );
    177177       
    178178        jabber_write_packet( gc, node );
  • protocols/jabber/jabber.h

    r038d17f r861c199  
    6969};
    7070
    71 typedef xt_status (*jabber_cache_event) ( struct gaim_connection *gc, struct xt_node *packet );
     71typedef xt_status (*jabber_cache_event) ( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig );
    7272
    7373struct jabber_cache_entry
     
    7979/* iq.c */
    8080xt_status jabber_pkt_iq( struct xt_node *node, gpointer data );
    81 int jabber_start_iq_auth( struct gaim_connection *gc );
     81int jabber_init_iq_auth( struct gaim_connection *gc );
     82xt_status jabber_pkt_bind_sess( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig );
    8283int jabber_get_roster( struct gaim_connection *gc );
    8384int jabber_add_to_roster( struct gaim_connection *gc, char *handle, char *name );
     
    9697char *set_eval_tls( set_t *set, char *value );
    9798struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children );
    98 void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node );
     99void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node, jabber_cache_event func );
    99100struct xt_node *jabber_cache_get( struct gaim_connection *gc, char *id );
    100101void jabber_cache_entry_free( gpointer entry );
  • protocols/jabber/jabber_util.c

    r038d17f r861c199  
    8282   them when you receive the response. Use this BEFORE sending the packet so
    8383   it'll get an id= tag, and do NOT free() the packet after writing it! */
    84 void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node )
     84void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node, jabber_cache_event func )
    8585{
    8686        struct jabber_data *jd = gc->proto_data;
     
    9292       
    9393        entry->node = node;
     94        entry->func = func;
    9495        g_hash_table_insert( jd->node_cache, xt_find_attr( node, "id" ), entry );
    95 }
    96 
    97 struct xt_node *jabber_cache_get( struct gaim_connection *gc, char *id )
    98 {
    99         struct jabber_data *jd = gc->proto_data;
    100         struct jabber_cache_entry *entry = g_hash_table_lookup( jd->node_cache, id );
    101        
    102         return entry ? entry->node : NULL;
    10396}
    10497
     
    113106gboolean jabber_cache_clean_entry( gpointer key, gpointer entry, gpointer nullpointer );
    114107
     108/* This one should be called from time to time (from keepalive, in this case)
     109   to make sure things don't stay in the node cache forever. By marking nodes
     110   during the first run and deleting marked nodes during a next run, every
     111   node should be available in the cache for at least a minute (assuming the
     112   function is indeed called every minute). */
    115113void jabber_cache_clean( struct gaim_connection *gc )
    116114{
Note: See TracChangeset for help on using the changeset viewer.