Changeset 0fbd3a6d for protocols/jabber


Ignore:
Timestamp:
2007-12-19T00:24:32Z (17 years ago)
Author:
ulim <a.sporto+bee@…>
Branches:
master
Children:
1ba7e8f
Parents:
793cc25 (diff), 2379566 (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:

Now with sending via a proxy. The proxy is automatically discovered from your
jabber server.

Also merged in revs 279..288 from upstream (e.g. PING)

Location:
protocols/jabber
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • protocols/jabber/conference.c

    r793cc25 r0fbd3a6d  
    174174       
    175175        return 1;
     176}
     177
     178void jabber_chat_invite( struct groupchat *c, char *who, char *message )
     179{
     180        struct xt_node *node;
     181        struct im_connection *ic = c->ic;
     182        struct jabber_chat *jc = c->data;
     183
     184        node = xt_new_node( "reason", message, NULL );
     185
     186        node = xt_new_node( "invite", NULL, node );
     187        xt_add_attr( node, "to", who );
     188
     189        node = xt_new_node( "x", NULL, node );
     190        xt_add_attr( node, "xmlns", XMLNS_MUC_USER );
     191       
     192        node = jabber_make_packet( "message", NULL, jc->name, node );
     193
     194        jabber_write_packet( ic, node );
     195
     196        xt_free_node( node );
    176197}
    177198
  • protocols/jabber/io.c

    r793cc25 r0fbd3a6d  
    120120                return TRUE;
    121121        }
    122         else if( st == 0 || ( st < 0 && !sockerr_again() ) )
     122        else if( st == 0 || ( st < 0 && !ssl_sockerr_again( jd->ssl ) ) )
    123123        {
    124124                /* Set fd to -1 to make sure we won't write to it anymore. */
     
    231231                }
    232232        }
    233         else if( st == 0 || ( st < 0 && !sockerr_again() ) )
     233        else if( st == 0 || ( st < 0 && !ssl_sockerr_again( jd->ssl ) ) )
    234234        {
    235235                closesocket( jd->fd );
  • protocols/jabber/iq.c

    r793cc25 r0fbd3a6d  
    5050        else if( strcmp( type, "get" ) == 0 )
    5151        {
    52                 if( !( c = xt_find_node( node->children, "query" ) ) ||
     52                if( !( ( c = xt_find_node( node->children, "query" ) ) ||
     53                       ( c = xt_find_node( node->children, "ping" ) ) ) || /* O_o WHAT is wrong with just <query/> ????? */
    5354                    !( s = xt_find_attr( c, "xmlns" ) ) )
    5455                {
     
    8182                        xt_add_child( reply, xt_new_node( "tz", buf, NULL ) );
    8283                }
    83                 else if( strcmp( s, XMLNS_DISCOVER ) == 0 )
     84                else if( strcmp( s, XMLNS_PING ) == 0 )
     85                {
     86                        xt_free_node( reply );
     87                        reply = jabber_make_packet( "iq", "result", xt_find_attr( node, "from" ), NULL );
     88                        if( ( s = xt_find_attr( node, "id" ) ) )
     89                                xt_add_attr( reply, "id", s );
     90                        pack = 0;
     91                }
     92                else if( strcmp( s, XMLNS_DISCO_INFO ) == 0 )
    8493                {
    8594                        const char *features[] = { XMLNS_VERSION,
     
    8796                                                   XMLNS_CHATSTATES,
    8897                                                   XMLNS_MUC,
     98                                                   XMLNS_PING,
    8999                                                   XMLNS_SI,
    90100                                                   XMLNS_BYTESTREAMS,
     
    565575        return st;
    566576}
     577
     578xt_status jabber_iq_parse_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig );
     579
     580xt_status jabber_iq_query_features( struct im_connection *ic, char *bare_jid )
     581{
     582        struct xt_node *node, *query;
     583        struct jabber_buddy *bud;
     584       
     585        if( ( bud = jabber_buddy_by_jid( ic, bare_jid , 0 ) ) == NULL )
     586        {
     587                /* Who cares about the unknown... */
     588                imcb_log( ic, "Couldnt find the man: %s", bare_jid);
     589                return 0;
     590        }
     591       
     592        if( bud->features ) /* been here already */
     593                return XT_HANDLED;
     594       
     595        node = xt_new_node( "query", NULL, NULL );
     596        xt_add_attr( node, "xmlns", XMLNS_DISCO_INFO );
     597       
     598        if( !( query = jabber_make_packet( "iq", "get", bare_jid, node ) ) )
     599        {
     600                imcb_log( ic, "WARNING: Couldn't generate feature query" );
     601                xt_free_node( node );
     602        }
     603
     604        jabber_cache_add( ic, query, jabber_iq_parse_features );
     605
     606        return jabber_write_packet( ic, query );
     607}
     608
     609xt_status jabber_iq_parse_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig )
     610{
     611        struct xt_node *c;
     612        struct jabber_buddy *bud;
     613        char *feature;
     614
     615        if( !( c = xt_find_node( node->children, "query" ) ) ||
     616            !( strcmp( xt_find_attr( c, "xmlns" ), XMLNS_DISCO_INFO ) == 0 ) )
     617        {
     618                imcb_log( ic, "WARNING: Received incomplete IQ-result packet for discover" );
     619                return XT_HANDLED;
     620        }
     621        if( ( bud = jabber_buddy_by_jid( ic, xt_find_attr( node, "from") , 0 ) ) == NULL )
     622        {
     623                /* Who cares about the unknown... */
     624                imcb_log( ic, "Couldnt find the man: %s", xt_find_attr( node, "from"));
     625                return 0;
     626        }
     627       
     628        c = c->children;
     629        while( ( c = xt_find_node( c, "feature" ) ) ) {
     630                feature = xt_find_attr( c, "var" );
     631                bud->features = g_slist_append(bud->features, g_strdup(feature) );
     632                c = c->next;
     633        }
     634
     635        return XT_HANDLED;
     636}
     637
     638xt_status jabber_iq_parse_server_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig );
     639
     640xt_status jabber_iq_query_server( struct im_connection *ic, char *jid, char *xmlns )
     641{
     642        struct xt_node *node, *query;
     643        struct jabber_data *jd = ic->proto_data;
     644       
     645        node = xt_new_node( "query", NULL, NULL );
     646        xt_add_attr( node, "xmlns", xmlns );
     647       
     648        if( !( query = jabber_make_packet( "iq", "get", jid, node ) ) )
     649        {
     650                imcb_log( ic, "WARNING: Couldn't generate server query" );
     651                xt_free_node( node );
     652        }
     653
     654        jd->have_streamhosts--;
     655        jabber_cache_add( ic, query, jabber_iq_parse_server_features );
     656
     657        return jabber_write_packet( ic, query );
     658}
     659
     660/*
     661 * Query the server for "items", query each "item" for identities, query each "item" that's a proxy for it's bytestream info
     662 */
     663xt_status jabber_iq_parse_server_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig )
     664{
     665        struct xt_node *c;
     666        struct jabber_data *jd = ic->proto_data;
     667
     668        if( !( c = xt_find_node( node->children, "query" ) ) ||
     669            !xt_find_attr( node, "from" ) )
     670        {
     671                imcb_log( ic, "WARNING: Received incomplete IQ-result packet for discover" );
     672                return XT_HANDLED;
     673        }
     674
     675        jd->have_streamhosts++;
     676
     677        if( strcmp( xt_find_attr( c, "xmlns" ), XMLNS_DISCO_ITEMS ) == 0 )
     678        {
     679                char *item, *itemjid;
     680
     681                /* answer from server */
     682       
     683                c = c->children;
     684                while( ( c = xt_find_node( c, "item" ) ) )
     685                {
     686                        item = xt_find_attr( c, "name" );
     687                        itemjid = xt_find_attr( c, "jid" );
     688
     689                        jabber_iq_query_server( ic, itemjid, XMLNS_DISCO_INFO );
     690
     691                        c = c->next;
     692                }
     693        } else if( strcmp( xt_find_attr( c, "xmlns" ), XMLNS_DISCO_INFO ) == 0 )
     694        {
     695                char *category, *type;
     696
     697                /* answer from potential proxy */
     698
     699                c = c->children;
     700                while( ( c = xt_find_node( c, "identity" ) ) )
     701                {
     702                        category = xt_find_attr( c, "category" );
     703                        type = xt_find_attr( c, "type" );
     704
     705                        if( type && ( strcmp( type, "bytestreams" ) == 0 ) &&
     706                            category && ( strcmp( category, "proxy" ) == 0 ) )
     707                                jabber_iq_query_server( ic, xt_find_attr( node, "from" ), XMLNS_BYTESTREAMS );
     708
     709                        c = c->next;
     710                }
     711        } else if( strcmp( xt_find_attr( c, "xmlns" ), XMLNS_BYTESTREAMS ) == 0 )
     712        {
     713                char *host, *jid;
     714                int port;
     715
     716                /* answer from proxy */
     717
     718                if( ( c = xt_find_node( c->children, "streamhost" ) ) &&
     719                    ( host = xt_find_attr( c, "host" ) ) &&
     720                    ( port = atoi( xt_find_attr( c, "port" ) ) ) &&
     721                    ( jid = xt_find_attr( c, "jid" ) ) )
     722                {
     723                        jabber_streamhost_t *sh = g_new0( jabber_streamhost_t, 1 );
     724                        sh->jid = g_strdup( jid );
     725                        sh->host = g_strdup( host );
     726                        sprintf( sh->port, "%u", port );
     727
     728                        imcb_log( ic, "Proxy found: jid %s host %s port %u", jid, host, port );
     729                        jd->streamhosts = g_slist_append( jd->streamhosts, sh );
     730                }
     731        }
     732
     733        if( jd->have_streamhosts == 0 )
     734                jd->have_streamhosts++;
     735        return XT_HANDLED;
     736}
  • protocols/jabber/jabber.c

    r793cc25 r0fbd3a6d  
    7676        jd->username = g_strdup( acc->user );
    7777        jd->server = strchr( jd->username, '@' );
     78       
     79        jd->fd = jd->r_inpa = jd->w_inpa = -1;
    7880       
    7981        if( jd->server == NULL )
     
    232234        struct jabber_data *jd = ic->proto_data;
    233235       
    234         jabber_end_stream( ic );
     236        if( jd->fd >= 0 )
     237                jabber_end_stream( ic );
    235238       
    236239        while( ic->groupchats )
     
    250253                g_free( jd->txq );
    251254       
    252         g_hash_table_destroy( jd->node_cache );
     255        if( jd->node_cache )
     256                g_hash_table_destroy( jd->node_cache );
    253257       
    254258        xt_free( jd->xt );
     
    421425        if( c )
    422426                jabber_chat_leave( c, NULL );
     427}
     428
     429static void jabber_chat_invite_( struct groupchat *c, char *who, char *msg )
     430{
     431        struct jabber_chat *jc = c->data;
     432        gchar *msg_alt = NULL;
     433
     434        if( msg == NULL )
     435                msg_alt = g_strdup_printf( "%s invited you to %s", c->ic->acc->user, jc->name );
     436       
     437        if( c && who )
     438                jabber_chat_invite( c, who, msg ? msg : msg_alt );
     439       
     440        g_free( msg_alt );
    423441}
    424442
     
    494512        ret->chat_msg = jabber_chat_msg_;
    495513        ret->chat_topic = jabber_chat_topic_;
    496 //      ret->chat_invite = jabber_chat_invite;
     514        ret->chat_invite = jabber_chat_invite_;
    497515        ret->chat_leave = jabber_chat_leave_;
    498516        ret->chat_join = jabber_chat_join_;
  • protocols/jabber/jabber.h

    r793cc25 r0fbd3a6d  
    5757} jabber_buddy_flags_t;
    5858
     59/* Stores a streamhost's(a.k.a. proxy) data */
     60typedef struct
     61{
     62        char *jid;
     63        char *host;
     64        char port[6];
     65} jabber_streamhost_t;
     66
    5967struct jabber_data
    6068{
     
    8391
    8492        GSList *filetransfers;
     93        GSList *streamhosts;
     94        int have_streamhosts;
    8595};
    8696
     
    111121        struct jabber_away_state *away_state;
    112122        char *away_message;
     123        GSList *features;
    113124       
    114125        time_t last_act;
     
    178189#define XMLNS_VERSION      "jabber:iq:version"                                   /* XEP-0092 */
    179190#define XMLNS_TIME         "jabber:iq:time"                                      /* XEP-0090 */
     191#define XMLNS_PING         "urn:xmpp:ping"                                       /* XEP-0199 */
    180192#define XMLNS_VCARD        "vcard-temp"                                          /* XEP-0054 */
    181193#define XMLNS_DELAY        "jabber:x:delay"                                      /* XEP-0091 */
    182194#define XMLNS_XDATA        "jabber:x:data"                                       /* XEP-0004 */
    183195#define XMLNS_CHATSTATES   "http://jabber.org/protocol/chatstates"               /* XEP-0085 */
    184 #define XMLNS_DISCOVER     "http://jabber.org/protocol/disco#info"               /* XEP-0030 */
     196#define XMLNS_DISCO_INFO   "http://jabber.org/protocol/disco#info"               /* XEP-0030 */
     197#define XMLNS_DISCO_ITEMS  "http://jabber.org/protocol/disco#items"              /* XEP-0030 */
    185198#define XMLNS_MUC          "http://jabber.org/protocol/muc"                      /* XEP-0045 */
    186199#define XMLNS_MUC_USER     "http://jabber.org/protocol/muc#user"                 /* XEP-0045 */
     
    199212int jabber_add_to_roster( struct im_connection *ic, char *handle, char *name );
    200213int jabber_remove_from_roster( struct im_connection *ic, char *handle );
     214xt_status jabber_iq_query_features( struct im_connection *ic, char *bare_jid );
     215xt_status jabber_iq_query_server( struct im_connection *ic, char *jid, char *xmlns );
    201216
    202217/* si.c */
     
    279294void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node );
    280295void jabber_chat_pkt_message( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node );
     296void jabber_chat_invite( struct groupchat *c, char *who, char *message );
    281297
    282298#endif
  • protocols/jabber/s5bytestream.c

    r793cc25 r0fbd3a6d  
    3030        struct jabber_transfer *tf;
    3131
    32         /* <query> element and <streamhost> elements */
    33         struct xt_node *qnode, *shnode;
     32        jabber_streamhost_t *sh;
     33        GSList *streamhosts;
    3434
    3535        enum
     
    7474gboolean jabber_bs_abort( struct bs_transfer *bt, char *format, ... );
    7575void jabber_bs_canceled( file_transfer_t *ft , char *reason );
    76 void jabber_bs_free_transfer( file_transfer_t *ft);
     76void jabber_bs_free_transfer( file_transfer_t *ft );
    7777gboolean jabber_bs_connect_timeout( gpointer data, gint fd, b_input_condition cond );
    7878gboolean jabber_bs_poll( struct bs_transfer *bt, int fd, short *revents );
     
    8484gboolean jabber_bs_recv_handshake( gpointer data, gint fd, b_input_condition cond );
    8585gboolean jabber_bs_recv_handshake_abort( struct bs_transfer *bt, char *error );
    86 int jabber_bs_recv_request( struct im_connection *ic, struct xt_node *node, struct xt_node *qnode);
     86int jabber_bs_recv_request( struct im_connection *ic, struct xt_node *node, struct xt_node *qnode );
    8787
    8888gboolean jabber_bs_send_handshake_abort( struct bs_transfer *bt, char *error );
    89 gboolean jabber_bs_send_request( struct jabber_transfer *tf, char *host, char *port );
     89gboolean jabber_bs_send_request( struct jabber_transfer *tf, GSList *streamhosts );
    9090gboolean jabber_bs_send_handshake( gpointer data, gint fd, b_input_condition cond );
    9191gboolean jabber_bs_send_listen( struct bs_transfer *bt, struct sockaddr_storage *saddr, char *host, char *port );
     92static xt_status jabber_bs_send_handle_activate( struct im_connection *ic, struct xt_node *node, struct xt_node *orig );
     93void jabber_bs_send_activate( struct bs_transfer *bt );
    9294
    9395/*
     
    9799        struct jabber_transfer *tf = ft->data;
    98100        struct bs_transfer *bt = tf->streamhandle;
     101        jabber_streamhost_t *sh;
    99102
    100103        if ( tf->watch_in )
     
    105108       
    106109        g_free( bt->pseudoadr );
    107         xt_free_node( bt->qnode );
     110
     111        while( bt->streamhosts )
     112        {
     113                sh = bt->streamhosts->data;
     114                bt->streamhosts = g_slist_remove( bt->streamhosts, sh );
     115                g_free( sh->jid );
     116                g_free( sh->host );
     117                g_free( sh );
     118        }
     119       
    108120        g_free( bt );
    109121
     
    111123}
    112124
     125/*
     126 * Checks if buflen data is available on the socket and
     127 * writes it to buffer if that's the case.
     128 */
    113129gboolean jabber_bs_peek( struct bs_transfer *bt, void *buffer, int buflen )
    114130{
     
    147163}
    148164
     165/*
     166 * Polls the socket, checks for errors and removes a connect timer
     167 * if there is one.
     168 */
    149169gboolean jabber_bs_poll( struct bs_transfer *bt, int fd, short *revents )
    150170{
     
    181201}
    182202
     203/*
     204 * Used for receive and send path.
     205 */
    183206gboolean jabber_bs_abort( struct bs_transfer *bt, char *format, ... )
    184207{
     
    191214        va_end( params );
    192215        if( bt->tf->ft->sending )
     216                return jabber_bs_send_handshake_abort( bt, error );
     217        else
    193218                return jabber_bs_recv_handshake_abort( bt, error );
    194         else
    195                 return jabber_bs_send_handshake_abort( bt, error );
    196219}
    197220
     
    214237        GSList *tflist;
    215238        struct bs_transfer *bt;
     239        GSList *shlist=NULL;
     240        struct xt_node *shnode;
    216241
    217242        sha1_state_t sha;
     
    233258        {
    234259                imcb_log( ic, "WARNING: Received SI Request for unsupported bytestream mode %s", xt_find_attr( qnode, "mode" ) );
     260                return XT_HANDLED;
     261        }
     262
     263        shnode = qnode->children;
     264        while( ( shnode = xt_find_node( shnode, "streamhost" ) ) )
     265        {
     266                char *jid, *host;
     267                int port;
     268                if( ( jid = xt_find_attr( shnode, "jid" ) ) &&
     269                    ( host = xt_find_attr( shnode, "host" ) ) &&
     270                    ( ( port = atoi( xt_find_attr( shnode, "port" ) ) ) ) )
     271                {
     272                        jabber_streamhost_t *sh = g_new0( jabber_streamhost_t, 1 );
     273                        sh->jid = g_strdup(jid);
     274                        sh->host = g_strdup(host);
     275                        sprintf( sh->port, "%u", port );
     276                        shlist = g_slist_append( shlist, sh );
     277                }
     278                shnode = shnode->next;
     279        }
     280       
     281        if( !shlist )
     282        {
     283                imcb_log( ic, "WARNING: Received incomplete SI bytestream request, no parseable streamhost entries");
    235284                return XT_HANDLED;
    236285        }
     
    274323        bt = g_new0( struct bs_transfer, 1 );
    275324        bt->tf = tf;
    276         bt->qnode = xt_dup( qnode );
    277         bt->shnode = bt->qnode->children;
     325        bt->streamhosts = shlist;
     326        bt->sh = shlist->data;
    278327        bt->phase = BS_PHASE_CONNECT;
    279328        bt->pseudoadr = g_strdup( hash_hex );
     
    285334        return XT_HANDLED;
    286335}
     336
    287337/*
    288338 * This is what a protocol handshake can look like in cooperative multitasking :)
     
    305355        case BS_PHASE_CONNECT:
    306356                {
    307                         struct xt_node *c;
    308                         char *host, *port;
    309357                        struct addrinfo hints, *rp;
    310358
    311                         if( ( c = bt->shnode = xt_find_node( bt->shnode, "streamhost" ) ) &&
    312                             ( port = xt_find_attr( c, "port" ) ) &&
    313                             ( host = xt_find_attr( c, "host" ) ) &&
    314                             xt_find_attr( c, "jid" ) )
    315                         {
    316                                 memset( &hints, 0, sizeof( struct addrinfo ) );
    317                                 hints.ai_socktype = SOCK_STREAM;
    318 
    319                                 if ( getaddrinfo( host, port, &hints, &rp ) != 0 )
    320                                         return jabber_bs_abort( bt, "getaddrinfo() failed: %s", strerror( errno ) );
    321 
    322                                 ASSERTSOCKOP( bt->tf->fd = fd = socket( rp->ai_family, rp->ai_socktype, 0 ), "Opening socket" );
    323 
    324                                 sock_make_nonblocking( fd );
    325 
    326                                 imcb_log( bt->tf->ic, "File %s: Connecting to streamhost %s:%s", bt->tf->ft->file_name, host, port );
    327 
    328                                 if( ( connect( fd, rp->ai_addr, rp->ai_addrlen ) == -1 ) &&
    329                                     ( errno != EINPROGRESS ) )
    330                                         return jabber_bs_abort( bt , "connect() failed: %s", strerror( errno ) );
    331 
    332                                 freeaddrinfo( rp );
    333 
    334                                 bt->phase = BS_PHASE_CONNECTED;
    335                                
    336                                 bt->tf->watch_out = b_input_add( fd, GAIM_INPUT_WRITE, jabber_bs_recv_handshake, bt );
    337 
    338                                 /* since it takes forever(3mins?) till connect() fails on itself we schedule a timeout */
    339                                 bt->connect_timeout = b_timeout_add( JABBER_BS_CONTIMEOUT * 1000, jabber_bs_connect_timeout, bt );
    340 
    341                                 bt->tf->watch_in = 0;
    342                                 return FALSE;
    343                         } else
    344                                 return jabber_bs_abort( bt, c ? "incomplete streamhost entry: host=%s port=%s jid=%s" : NULL,
    345                                                                   host, port, xt_find_attr( c, "jid" ) );
     359                        memset( &hints, 0, sizeof( struct addrinfo ) );
     360                        hints.ai_socktype = SOCK_STREAM;
     361
     362                        if ( getaddrinfo( bt->sh->host, bt->sh->port, &hints, &rp ) != 0 )
     363                                return jabber_bs_abort( bt, "getaddrinfo() failed: %s", strerror( errno ) );
     364
     365                        ASSERTSOCKOP( bt->tf->fd = fd = socket( rp->ai_family, rp->ai_socktype, 0 ), "Opening socket" );
     366
     367                        sock_make_nonblocking( fd );
     368
     369                        imcb_log( bt->tf->ic, "File %s: Connecting to streamhost %s:%s", bt->tf->ft->file_name, bt->sh->host, bt->sh->port );
     370
     371                        if( ( connect( fd, rp->ai_addr, rp->ai_addrlen ) == -1 ) &&
     372                            ( errno != EINPROGRESS ) )
     373                                return jabber_bs_abort( bt , "connect() failed: %s", strerror( errno ) );
     374
     375                        freeaddrinfo( rp );
     376
     377                        bt->phase = BS_PHASE_CONNECTED;
     378                       
     379                        bt->tf->watch_out = b_input_add( fd, GAIM_INPUT_WRITE, jabber_bs_recv_handshake, bt );
     380
     381                        /* since it takes forever(3mins?) till connect() fails on itself we schedule a timeout */
     382                        bt->connect_timeout = b_timeout_add( JABBER_BS_CONTIMEOUT * 1000, jabber_bs_connect_timeout, bt );
     383
     384                        bt->tf->watch_in = 0;
     385                        return FALSE;
    346386                }
    347387        case BS_PHASE_CONNECTED:
     
    422462                                        socks5_reply.addrlen);
    423463
    424                         jabber_bs_recv_answer_request( bt );
     464                        if( bt->tf->ft->sending )
     465                                jabber_bs_send_activate( bt );
     466                        else
     467                                jabber_bs_recv_answer_request( bt );
    425468
    426469                        return FALSE;
     
    447490        struct jabber_transfer *tf = bt->tf;
    448491        struct xt_node *reply, *iqnode;
    449 
    450         if( bt->shnode )
    451         {
    452                 imcb_log( tf->ic, "Transferring file %s: connection to streamhost %s:%s failed (%s)",
    453                           tf->ft->file_name,
    454                           xt_find_attr( bt->shnode, "host" ),
    455                           xt_find_attr( bt->shnode, "port" ),
    456                           error );
    457 
    458                 /* Alright, this streamhost failed, let's try the next... */
    459                 bt->phase = BS_PHASE_CONNECT;
    460                 bt->shnode = bt->shnode->next;
    461                
    462                 /* the if is not neccessary but saves us one recursion */
    463                 if( bt->shnode )
    464                         return jabber_bs_recv_handshake( bt, 0, 0 );
    465         }
     492        GSList *shlist;
     493
     494        imcb_log( tf->ic, "Transferring file %s: connection to streamhost %s:%s failed (%s)",
     495                  tf->ft->file_name,
     496                  bt->sh->host,
     497                  bt->sh->port,
     498                  error );
     499
     500        /* Alright, this streamhost failed, let's try the next... */
     501        bt->phase = BS_PHASE_CONNECT;
     502        shlist = g_slist_find( bt->streamhosts, bt->sh );
     503        if( shlist && shlist->next )
     504        {
     505                bt->sh = shlist->next->data;
     506                return jabber_bs_recv_handshake( bt, 0, 0 );
     507        }
     508
    466509
    467510        /* out of stream hosts */
     
    495538        imcb_log( tf->ic, "File %s: established SOCKS5 connection to %s:%s",
    496539                  tf->ft->file_name,
    497                   xt_find_attr( bt->shnode, "host" ),
    498                   xt_find_attr( bt->shnode, "port" ) );
     540                  bt->sh->host,
     541                  bt->sh->port );
    499542
    500543        tf->ft->data = tf;
    501         tf->ft->started = time( NULL );
    502544        tf->watch_in = b_input_add( tf->fd, GAIM_INPUT_READ, jabber_bs_recv_read, bt );
    503545        tf->ft->write_request = jabber_bs_recv_write_request;
    504546
    505547        reply = xt_new_node( "streamhost-used", NULL, NULL );
    506         xt_add_attr( reply, "jid", xt_find_attr( bt->shnode, "jid" ) );
     548        xt_add_attr( reply, "jid", bt->sh->jid );
    507549
    508550        reply = xt_new_node( "query", NULL, reply );
     
    551593                return jabber_bs_abort( bt, "Remote end closed connection" );
    552594       
     595        if( tf->bytesread == 0 )
     596                tf->ft->started = time( NULL );
     597
    553598        tf->bytesread += ret;
    554599
     
    603648                return jabber_bs_abort( bt, "BUG: write() called while watching " );
    604649       
     650        /* TODO: catch broken pipe */
    605651        ASSERTSOCKOP( ret = send( tf->fd, buffer, len, 0 ), "Sending" );
     652
     653        if( tf->byteswritten == 0 )
     654                tf->ft->started = time( NULL );
    606655
    607656        tf->byteswritten += ret;
     
    665714        tf->accepted = TRUE;
    666715
    667         if( bt->phase == BS_PHASE_REPLY )
    668         {
    669                 /* handshake went through, let's start transferring */
    670                 tf->ft->started = time( NULL );
    671                 tf->ft->write_request( tf->ft );
     716        if( strcmp( jid, tf->ini_jid ) == 0 )
     717        {
     718                /* we're streamhost and target */
     719                if( bt->phase == BS_PHASE_REPLY )
     720                {
     721                        /* handshake went through, let's start transferring */
     722                        tf->ft->write_request( tf->ft );
     723                }
     724        } else
     725        {
     726                /* using a proxy */
     727                GSList *shlist;
     728                for( shlist = jd->streamhosts ; shlist ; shlist = g_slist_next( shlist ) )
     729                {
     730                        jabber_streamhost_t *sh = shlist->data;
     731                        if( strcmp( sh->jid, jid ) == 0 )
     732                        {
     733                                bt->sh = sh;
     734                                jabber_bs_recv_handshake( bt, 0, 0 );
     735                                return XT_HANDLED;
     736                        }
     737                }
     738
     739                imcb_log( ic, "WARNING: Received SOCKS5 bytestream reply with unknown streamhost %s", jid );
    672740        }
    673741
     
    675743}
    676744
     745/*
     746 * Tell the proxy to activate the stream. Looks like this:
     747 *
     748 * <iq type=set>
     749 *      <query xmlns=bs sid=sid>
     750 *              <activate>tgt_jid</activate>
     751 *      </query>
     752 * </iq>
     753 */
     754void jabber_bs_send_activate( struct bs_transfer *bt )
     755{
     756        struct xt_node *node;
     757
     758        node = xt_new_node( "activate", bt->tf->tgt_jid, NULL );
     759        node = xt_new_node( "query", NULL, node );
     760        xt_add_attr( node, "xmlns", XMLNS_BYTESTREAMS );
     761        xt_add_attr( node, "sid", bt->tf->sid );
     762        node = jabber_make_packet( "iq", "set", bt->sh->jid, node );
     763
     764        jabber_cache_add( bt->tf->ic, node, jabber_bs_send_handle_activate );
     765
     766        jabber_write_packet( bt->tf->ic, node );
     767}
     768
     769/*
     770 * The proxy has activated the bytestream.
     771 * We can finally start pushing some data out.
     772 */
     773static xt_status jabber_bs_send_handle_activate( struct im_connection *ic, struct xt_node *node, struct xt_node *orig )
     774{
     775        char *sid;
     776        GSList *tflist;
     777        struct jabber_transfer *tf;
     778        struct xt_node *query;
     779        struct jabber_data *jd = ic->proto_data;
     780
     781        query = xt_find_node( orig->children, "query" );
     782        sid = xt_find_attr( query, "sid" );
     783
     784        for( tflist = jd->filetransfers ; tflist; tflist = g_slist_next(tflist) )
     785        {
     786                struct jabber_transfer *tft = tflist->data;
     787                if( ( strcmp( tft->sid, sid ) == 0 ) )
     788                {
     789                        tf = tft;
     790                        break;
     791                }
     792        }
     793
     794        if( !tf )
     795        {
     796                imcb_log( ic, "WARNING: Received SOCKS5 bytestream activation for unknown stream" );
     797                return XT_HANDLED;
     798        }
     799
     800        /* handshake went through, let's start transferring */
     801        tf->ft->write_request( tf->ft );
     802
     803        return XT_HANDLED;
     804}
     805
     806/*
     807 * Starts a bytestream.
     808 */
    677809gboolean jabber_bs_send_start( struct jabber_transfer *tf )
    678810{
    679         char host[INET6_ADDRSTRLEN], port[6];
     811        char host[INET6_ADDRSTRLEN];
    680812        struct bs_transfer *bt;
    681813        sha1_state_t sha;
    682814        char hash_hex[41];
    683815        unsigned char hash[20];
    684         int i;
     816        int i,ret;
     817        struct jabber_data *jd = tf->ic->proto_data;
     818        jabber_streamhost_t sh;
     819        GSList *streamhosts = jd->streamhosts;
    685820
    686821        /* SHA1( SID + Initiator JID + Target JID ) is given to the streamhost which it will match against the initiator's value */
     
    702837        tf->ft->canceled = jabber_bs_canceled;
    703838
    704         if ( !jabber_bs_send_listen( bt, &tf->saddr, host, port ) )
     839        if ( !jabber_bs_send_listen( bt, &tf->saddr, sh.host = host, sh.port ) )
    705840                return FALSE;
    706841
    707842        bt->tf->watch_in = b_input_add( tf->fd, GAIM_INPUT_READ, jabber_bs_send_handshake, bt );
    708843        bt->connect_timeout = b_timeout_add( JABBER_BS_LISTEN_TIMEOUT * 1000, jabber_bs_connect_timeout, bt );
    709         return jabber_bs_send_request( tf, host, port );
    710 }
    711 
    712 gboolean jabber_bs_send_request( struct jabber_transfer *tf, char *host, char *port )
    713 {
    714         struct xt_node *sh, *query, *iq;
    715 
    716         sh = xt_new_node( "streamhost", NULL, NULL );
    717         xt_add_attr( sh, "jid", tf->ini_jid );
    718         xt_add_attr( sh, "host", host );
    719         xt_add_attr( sh, "port", port );
     844
     845        sh.jid = tf->ini_jid;
     846
     847        /* temporarily add listen address to streamhosts, send the request and remove it */
     848        streamhosts = g_slist_prepend( streamhosts, &sh );
     849        ret = jabber_bs_send_request( tf, streamhosts);
     850        streamhosts = g_slist_remove( streamhosts, &sh );
     851
     852        return ret;
     853}
     854
     855gboolean jabber_bs_send_request( struct jabber_transfer *tf, GSList *streamhosts )
     856{
     857        struct xt_node *shnode, *query, *iq;
    720858
    721859        query = xt_new_node( "query", NULL, NULL );
     
    723861        xt_add_attr( query, "sid", tf->sid );
    724862        xt_add_attr( query, "mode", "tcp" );
    725         xt_add_child( query, sh );
     863
     864        while( streamhosts ) {
     865                jabber_streamhost_t *sh = streamhosts->data;
     866                shnode = xt_new_node( "streamhost", NULL, NULL );
     867                xt_add_attr( shnode, "jid", sh->jid );
     868                xt_add_attr( shnode, "host", sh->host );
     869                xt_add_attr( shnode, "port", sh->port );
     870
     871                xt_add_child( query, shnode );
     872
     873                streamhosts = g_slist_next( streamhosts );
     874        }
     875
    726876
    727877        iq = jabber_make_packet( "iq", "set", tf->tgt_jid, query );
     
    739889        struct jabber_transfer *tf = bt->tf;
    740890
     891        /* TODO: did the receiver get here somehow??? */
    741892        imcb_log( tf->ic, "Transferring file %s: SOCKS5 handshake failed: %s",
    742893                  tf->ft->file_name,
     
    9011052                        {
    9021053                                /* streamhost-used message came already in(possible?), let's start sending */
    903                                 tf->ft->started = time( NULL );
    9041054                                tf->ft->write_request( tf->ft );
    9051055                        }
  • protocols/jabber/si.c

    r793cc25 r0fbd3a6d  
    8383        struct jabber_transfer *tf;
    8484        struct jabber_data *jd = ic->proto_data;
     85        char *server  = jd->server;
    8586
    8687        imcb_log( ic, "Trying to send %s(%zd bytes) to %s", ft->file_name, ft->file_size, who );
     
    9798        jd->filetransfers = g_slist_prepend( jd->filetransfers, tf );
    9899
     100        /* query the buddy's features */
     101        jabber_iq_query_features( ic, who );
     102
     103        /* query proxies from the server */
     104        if( !jd->have_streamhosts )
     105                jabber_iq_query_server( ic, server, XMLNS_DISCO_ITEMS );
     106
     107        /* send the request to our buddy */
    99108        jabber_si_send_request( ic, who, tf );
    100109
     110        /* and start the receive logic */
    101111        imcb_file_recv_start( ft );
    102112}
Note: See TracChangeset for help on using the changeset viewer.