Changeset dc0ba9c for protocols/jabber


Ignore:
Timestamp:
2007-12-18T02:07:59Z (17 years ago)
Author:
kenobi <kenobi@…>
Branches:
master
Children:
eded1f7
Parents:
8076ec0
Message:

sending via proxy

Location:
protocols/jabber
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • protocols/jabber/iq.c

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

    r8076ec0 rdc0ba9c  
    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;
     
    182193#define XMLNS_XDATA        "jabber:x:data"                                       /* XEP-0004 */
    183194#define XMLNS_CHATSTATES   "http://jabber.org/protocol/chatstates"               /* XEP-0085 */
    184 #define XMLNS_DISCOVER     "http://jabber.org/protocol/disco#info"               /* XEP-0030 */
     195#define XMLNS_DISCO_INFO   "http://jabber.org/protocol/disco#info"               /* XEP-0030 */
     196#define XMLNS_DISCO_ITEMS  "http://jabber.org/protocol/disco#items"              /* XEP-0030 */
    185197#define XMLNS_MUC          "http://jabber.org/protocol/muc"                      /* XEP-0045 */
    186198#define XMLNS_MUC_USER     "http://jabber.org/protocol/muc#user"                 /* XEP-0045 */
     
    199211int jabber_add_to_roster( struct im_connection *ic, char *handle, char *name );
    200212int jabber_remove_from_roster( struct im_connection *ic, char *handle );
     213xt_status jabber_iq_query_features( struct im_connection *ic, char *bare_jid );
     214xt_status jabber_iq_query_server( struct im_connection *ic, char *jid, char *xmlns );
    201215
    202216/* si.c */
  • protocols/jabber/s5bytestream.c

    r8076ec0 rdc0ba9c  
    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

    r8076ec0 rdc0ba9c  
    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.