Changeset 767a148 for protocols/jabber


Ignore:
Timestamp:
2010-03-21T16:06:31Z (14 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Branches:
master
Children:
1cc0df3, 85693e6
Parents:
545d7c0 (diff), a81d679 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merging in file transfer support. Most important points from my review
are fixed now, time to let it settle in and get people to try it.

Location:
protocols/jabber
Files:
2 added
5 edited

Legend:

Unmodified
Added
Removed
  • protocols/jabber/Makefile

    r545d7c0 r767a148  
    1010
    1111# [SH] Program variables
    12 objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o
     12objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o s5bytestream.o sasl.o si.o
    1313
    1414CFLAGS += -Wall
  • protocols/jabber/iq.c

    r545d7c0 r767a148  
    9191                        pack = 0;
    9292                }
    93                 else if( strcmp( s, XMLNS_DISCOVER ) == 0 )
    94                 {
    95                         const char *features[] = { XMLNS_DISCOVER,
     93                else if( strcmp( s, XMLNS_DISCO_INFO ) == 0 )
     94                {
     95                        const char *features[] = { XMLNS_DISCO_INFO,
    9696                                                   XMLNS_VERSION,
    9797                                                   XMLNS_TIME,
     
    9999                                                   XMLNS_MUC,
    100100                                                   XMLNS_PING,
     101                                                   XMLNS_SI,
     102                                                   XMLNS_BYTESTREAMS,
     103                                                   XMLNS_FILETRANSFER,
    101104                                                   NULL };
    102105                        const char **f;
     
    118121                {
    119122                        xt_free_node( reply );
    120                         reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel" );
     123                        reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel", NULL );
    121124                        pack = 0;
    122125                }
     
    124127        else if( strcmp( type, "set" ) == 0 )
    125128        {
    126                 if( !( c = xt_find_node( node->children, "query" ) ) ||
    127                     !( s = xt_find_attr( c, "xmlns" ) ) )
     129                if( ( c = xt_find_node( node->children, "si" ) ) &&
     130                    ( s = xt_find_attr( c, "xmlns" ) ) &&
     131                    ( strcmp( s, XMLNS_SI ) == 0 ) )
     132                {
     133                        return jabber_si_handle_request( ic, node, c );
     134                }
     135                else if( !( c = xt_find_node( node->children, "query" ) ) ||
     136                         !( s = xt_find_attr( c, "xmlns" ) ) )
    128137                {
    129138                        imcb_log( ic, "Warning: Received incomplete IQ-%s packet", type );
    130139                        return XT_HANDLED;
    131140                }
    132                
     141                else if( strcmp( s, XMLNS_ROSTER ) == 0 )
     142                {
    133143                /* This is a roster push. XMPP servers send this when someone
    134144                   was added to (or removed from) the buddy list. AFAIK they're
    135145                   sent even if we added this buddy in our own session. */
    136                 if( strcmp( s, XMLNS_ROSTER ) == 0 )
    137                 {
    138146                        int bare_len = strlen( ic->acc->user );
    139147                       
     
    152160                               
    153161                                xt_free_node( reply );
    154                                 reply = jabber_make_error_packet( node, "not-allowed", "cancel" );
     162                                reply = jabber_make_error_packet( node, "not-allowed", "cancel", NULL );
    155163                                pack = 0;
    156164                        }
    157165                }
     166                else if( strcmp( s, XMLNS_BYTESTREAMS ) == 0 )
     167                {
     168                        /* Bytestream Request (stage 2 of file transfer) */
     169                        return jabber_bs_recv_request( ic, node, c );
     170                }
    158171                else
    159172                {
    160173                        xt_free_node( reply );
    161                         reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel" );
     174                        reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel", NULL );
    162175                        pack = 0;
    163176                }
     
    609622        return st;
    610623}
     624
     625xt_status jabber_iq_parse_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig );
     626
     627xt_status jabber_iq_query_features( struct im_connection *ic, char *bare_jid )
     628{
     629        struct xt_node *node, *query;
     630        struct jabber_buddy *bud;
     631       
     632        if( ( bud = jabber_buddy_by_jid( ic, bare_jid , 0 ) ) == NULL )
     633        {
     634                /* Who cares about the unknown... */
     635                imcb_log( ic, "Couldn't find buddy: %s", bare_jid);
     636                return XT_HANDLED;
     637        }
     638       
     639        if( bud->features ) /* been here already */
     640                return XT_HANDLED;
     641       
     642        node = xt_new_node( "query", NULL, NULL );
     643        xt_add_attr( node, "xmlns", XMLNS_DISCO_INFO );
     644       
     645        if( !( query = jabber_make_packet( "iq", "get", bare_jid, node ) ) )
     646        {
     647                imcb_log( ic, "WARNING: Couldn't generate feature query" );
     648                xt_free_node( node );
     649                return XT_HANDLED;
     650        }
     651
     652        jabber_cache_add( ic, query, jabber_iq_parse_features );
     653
     654        return jabber_write_packet( ic, query ) ? XT_HANDLED : XT_ABORT;
     655}
     656
     657xt_status jabber_iq_parse_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig )
     658{
     659        struct xt_node *c;
     660        struct jabber_buddy *bud;
     661        char *feature, *xmlns, *from;
     662
     663        if( !( from = xt_find_attr( node, "from" ) ) ||
     664            !( c = xt_find_node( node->children, "query" ) ) ||
     665            !( xmlns = xt_find_attr( c, "xmlns" ) ) ||
     666            !( strcmp( xmlns, XMLNS_DISCO_INFO ) == 0 ) )
     667        {
     668                imcb_log( ic, "WARNING: Received incomplete IQ-result packet for discover" );
     669                return XT_HANDLED;
     670        }
     671        if( ( bud = jabber_buddy_by_jid( ic, from, 0 ) ) == NULL )
     672        {
     673                /* Who cares about the unknown... */
     674                imcb_log( ic, "Couldn't find buddy: %s", from );
     675                return XT_HANDLED;
     676        }
     677       
     678        c = c->children;
     679        while( ( c = xt_find_node( c, "feature" ) ) )
     680        {
     681                feature = xt_find_attr( c, "var" );
     682                if( feature )
     683                        bud->features = g_slist_append( bud->features, g_strdup( feature ) );
     684                c = c->next;
     685        }
     686
     687        return XT_HANDLED;
     688}
     689
     690xt_status jabber_iq_parse_server_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig );
     691
     692xt_status jabber_iq_query_server( struct im_connection *ic, char *jid, char *xmlns )
     693{
     694        struct xt_node *node, *query;
     695        struct jabber_data *jd = ic->proto_data;
     696       
     697        node = xt_new_node( "query", NULL, NULL );
     698        xt_add_attr( node, "xmlns", xmlns );
     699       
     700        if( !( query = jabber_make_packet( "iq", "get", jid, node ) ) )
     701        {
     702                imcb_log( ic, "WARNING: Couldn't generate server query" );
     703                xt_free_node( node );
     704        }
     705
     706        jd->have_streamhosts--;
     707        jabber_cache_add( ic, query, jabber_iq_parse_server_features );
     708
     709        return jabber_write_packet( ic, query ) ? XT_HANDLED : XT_ABORT;
     710}
     711
     712/*
     713 * Query the server for "items", query each "item" for identities, query each "item" that's a proxy for it's bytestream info
     714 */
     715xt_status jabber_iq_parse_server_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig )
     716{
     717        struct xt_node *c;
     718        struct jabber_data *jd = ic->proto_data;
     719        char *xmlns, *from;
     720
     721        if( !( c = xt_find_node( node->children, "query" ) ) ||
     722            !( from = xt_find_attr( node, "from" ) ) ||
     723            !( xmlns = xt_find_attr( c, "xmlns" ) ) )
     724        {
     725                imcb_log( ic, "WARNING: Received incomplete IQ-result packet for discover" );
     726                return XT_HANDLED;
     727        }
     728
     729        jd->have_streamhosts++;
     730
     731        if( strcmp( xmlns, XMLNS_DISCO_ITEMS ) == 0 )
     732        {
     733                char *itemjid;
     734
     735                /* answer from server */
     736       
     737                c = c->children;
     738                while( ( c = xt_find_node( c, "item" ) ) )
     739                {
     740                        itemjid = xt_find_attr( c, "jid" );
     741                       
     742                        if( itemjid )
     743                                jabber_iq_query_server( ic, itemjid, XMLNS_DISCO_INFO );
     744
     745                        c = c->next;
     746                }
     747        }
     748        else if( strcmp( xmlns, XMLNS_DISCO_INFO ) == 0 )
     749        {
     750                char *category, *type;
     751
     752                /* answer from potential proxy */
     753
     754                c = c->children;
     755                while( ( c = xt_find_node( c, "identity" ) ) )
     756                {
     757                        category = xt_find_attr( c, "category" );
     758                        type = xt_find_attr( c, "type" );
     759
     760                        if( type && ( strcmp( type, "bytestreams" ) == 0 ) &&
     761                            category && ( strcmp( category, "proxy" ) == 0 ) )
     762                                jabber_iq_query_server( ic, from, XMLNS_BYTESTREAMS );
     763
     764                        c = c->next;
     765                }
     766        }
     767        else if( strcmp( xmlns, XMLNS_BYTESTREAMS ) == 0 )
     768        {
     769                char *host, *jid, *port_s;
     770                int port;
     771
     772                /* answer from proxy */
     773
     774                if( ( c = xt_find_node( c->children, "streamhost" ) ) &&
     775                    ( host = xt_find_attr( c, "host" ) ) &&
     776                    ( port_s = xt_find_attr( c, "port" ) ) &&
     777                    ( sscanf( port_s, "%d", &port ) == 1 ) &&
     778                    ( jid = xt_find_attr( c, "jid" ) ) )
     779                {
     780                        jabber_streamhost_t *sh = g_new0( jabber_streamhost_t, 1 );
     781                       
     782                        sh->jid = g_strdup( jid );
     783                        sh->host = g_strdup( host );
     784                        g_snprintf( sh->port, sizeof( sh->port ), "%u", port );
     785
     786                        imcb_log( ic, "Proxy found: jid %s host %s port %u", jid, host, port );
     787                        jd->streamhosts = g_slist_append( jd->streamhosts, sh );
     788                }
     789        }
     790
     791        if( jd->have_streamhosts == 0 )
     792                jd->have_streamhosts++;
     793
     794        return XT_HANDLED;
     795}
  • protocols/jabber/jabber.c

    r545d7c0 r767a148  
    6565       
    6666        s = set_add( &acc->set, "priority", "0", set_eval_priority, acc );
     67
     68        s = set_add( &acc->set, "proxy", "<local>;<auto>", NULL, acc );
    6769       
    6870        s = set_add( &acc->set, "resource", "BitlBee", NULL, acc );
     
    264266        struct jabber_data *jd = ic->proto_data;
    265267       
     268        while( jd->filetransfers )
     269                imcb_file_canceled( ( ( struct jabber_transfer *) jd->filetransfers->data )->ft, "Logging out" );
     270
     271        while( jd->streamhosts )
     272        {
     273                jabber_streamhost_t *sh = jd->streamhosts->data;
     274                jd->streamhosts = g_slist_remove( jd->streamhosts, sh );
     275                g_free( sh->jid );
     276                g_free( sh->host );
     277                g_free( sh );
     278        }
     279
    266280        if( jd->fd >= 0 )
    267281                jabber_end_stream( ic );
     
    544558        ret->send_typing = jabber_send_typing;
    545559        ret->handle_cmp = g_strcasecmp;
     560        ret->transfer_request = jabber_si_transfer_request;
    546561
    547562        register_protocol( ret );
  • protocols/jabber/jabber.h

    r545d7c0 r767a148  
    6161} jabber_buddy_flags_t;
    6262
     63/* Stores a streamhost's (a.k.a. proxy) data */
     64typedef struct
     65{
     66        char *jid;
     67        char *host;
     68        char port[6];
     69} jabber_streamhost_t;
     70
    6371typedef enum
    6472{
     
    9199        GHashTable *node_cache;
    92100        GHashTable *buddies;
     101
     102        GSList *filetransfers;
     103        GSList *streamhosts;
     104        int have_streamhosts;
    93105};
    94106
     
    127139        struct jabber_away_state *away_state;
    128140        char *away_message;
     141        GSList *features;
    129142       
    130143        time_t last_msg;
     
    140153        char *my_full_jid; /* Separate copy because of case sensitivity. */
    141154        struct jabber_buddy *me;
     155};
     156
     157struct jabber_transfer
     158{
     159        /* bitlbee's handle for this transfer */
     160        file_transfer_t *ft;
     161
     162        /* the stream's private handle */
     163        gpointer streamhandle;
     164
     165        /* timeout for discover queries */
     166        gint disco_timeout;
     167        gint disco_timeout_fired;
     168
     169        struct im_connection *ic;
     170
     171        struct jabber_buddy *bud;
     172
     173        int watch_in;
     174        int watch_out;
     175
     176        char *ini_jid;
     177        char *tgt_jid;
     178        char *iq_id;
     179        char *sid;
     180        int accepted;
     181
     182        size_t bytesread, byteswritten;
     183        int fd;
     184        struct sockaddr_storage saddr;
    142185};
    143186
     
    167210
    168211/* Some supported extensions/legacy stuff */
    169 #define XMLNS_AUTH         "jabber:iq:auth"                     /* XEP-0078 */
    170 #define XMLNS_VERSION      "jabber:iq:version"                  /* XEP-0092 */
    171 #define XMLNS_TIME         "jabber:iq:time"                     /* XEP-0090 */
    172 #define XMLNS_PING         "urn:xmpp:ping"                      /* XEP-0199 */
    173 #define XMLNS_VCARD        "vcard-temp"                         /* XEP-0054 */
    174 #define XMLNS_DELAY        "jabber:x:delay"                     /* XEP-0091 */
    175 #define XMLNS_CHATSTATES   "http://jabber.org/protocol/chatstates"  /* 0085 */
    176 #define XMLNS_DISCOVER     "http://jabber.org/protocol/disco#info"  /* 0030 */
    177 #define XMLNS_MUC          "http://jabber.org/protocol/muc"     /* XEP-0045 */
    178 #define XMLNS_MUC_USER     "http://jabber.org/protocol/muc#user"/* XEP-0045 */
    179 #define XMLNS_CAPS         "http://jabber.org/protocol/caps"    /* XEP-0115 */
     212#define XMLNS_AUTH         "jabber:iq:auth"                                      /* XEP-0078 */
     213#define XMLNS_VERSION      "jabber:iq:version"                                   /* XEP-0092 */
     214#define XMLNS_TIME         "jabber:iq:time"                                      /* XEP-0090 */
     215#define XMLNS_PING         "urn:xmpp:ping"                                       /* XEP-0199 */
     216#define XMLNS_VCARD        "vcard-temp"                                          /* XEP-0054 */
     217#define XMLNS_DELAY        "jabber:x:delay"                                      /* XEP-0091 */
     218#define XMLNS_XDATA        "jabber:x:data"                                       /* XEP-0004 */
     219#define XMLNS_CHATSTATES   "http://jabber.org/protocol/chatstates"               /* XEP-0085 */
     220#define XMLNS_DISCO_INFO   "http://jabber.org/protocol/disco#info"               /* XEP-0030 */
     221#define XMLNS_DISCO_ITEMS  "http://jabber.org/protocol/disco#items"              /* XEP-0030 */
     222#define XMLNS_MUC          "http://jabber.org/protocol/muc"                      /* XEP-0045 */
     223#define XMLNS_MUC_USER     "http://jabber.org/protocol/muc#user"                 /* XEP-0045 */
     224#define XMLNS_CAPS         "http://jabber.org/protocol/caps"                     /* XEP-0115 */
     225#define XMLNS_FEATURE      "http://jabber.org/protocol/feature-neg"              /* XEP-0020 */
     226#define XMLNS_SI           "http://jabber.org/protocol/si"                       /* XEP-0095 */
     227#define XMLNS_FILETRANSFER "http://jabber.org/protocol/si/profile/file-transfer" /* XEP-0096 */
     228#define XMLNS_BYTESTREAMS  "http://jabber.org/protocol/bytestreams"              /* XEP-0065 */
     229#define XMLNS_IBB          "http://jabber.org/protocol/ibb"                      /* XEP-0047 */
    180230
    181231/* iq.c */
     
    187237int jabber_add_to_roster( struct im_connection *ic, char *handle, char *name );
    188238int jabber_remove_from_roster( struct im_connection *ic, char *handle );
     239xt_status jabber_iq_query_features( struct im_connection *ic, char *bare_jid );
     240xt_status jabber_iq_query_server( struct im_connection *ic, char *jid, char *xmlns );
     241
     242/* si.c */
     243int jabber_si_handle_request( struct im_connection *ic, struct xt_node *node, struct xt_node *sinode );
     244void jabber_si_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who );
     245void jabber_si_free_transfer( file_transfer_t *ft);
     246
     247/* s5bytestream.c */
     248int jabber_bs_recv_request( struct im_connection *ic, struct xt_node *node, struct xt_node *qnode);
     249gboolean jabber_bs_send_start( struct jabber_transfer *tf );
     250gboolean jabber_bs_send_write( file_transfer_t *ft, char *buffer, unsigned int len );
    189251
    190252/* message.c */
     
    200262char *set_eval_tls( set_t *set, char *value );
    201263struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children );
    202 struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type );
     264struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type, char *err_code );
    203265void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_cache_event func );
    204266struct xt_node *jabber_cache_get( struct im_connection *ic, char *id );
  • protocols/jabber/jabber_util.c

    r545d7c0 r767a148  
    9999}
    100100
    101 struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type )
     101struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type, char *err_code )
    102102{
    103103        struct xt_node *node, *c;
     
    111111        c = xt_new_node( "error", NULL, c );
    112112        xt_add_attr( c, "type", err_type );
     113       
     114        /* Add the error code, if present */
     115        if (err_code)
     116                xt_add_attr( c, "code", err_code );
    113117       
    114118        /* To make the actual error packet, we copy the original packet and
Note: See TracChangeset for help on using the changeset viewer.