Ignore:
Timestamp:
2007-12-03T14:28:45Z (16 years ago)
Author:
ulim <a.sporto+bee@…>
Branches:
master
Children:
dce3903
Parents:
2c2df7d
Message:

Intermediate commit. Sending seems to work. TODOs:

  • move from out_of_data to is_writable, eliminate buffers
  • implement "transfers reject [id]"
  • documentation in commands.xml
  • implement throughput and cummulative throughput boundaries
  • feature discovery before sending
  • implement sending over a proxy (proxy discovery, socks5 client handshake for sending, activate message)
  • integrate toxik-mek-ft
File:
1 edited

Legend:

Unmodified
Added
Removed
  • protocols/jabber/si.c

    r2c2df7d r2ff2076  
    2626
    2727void jabber_si_answer_request( file_transfer_t *ft );
    28 
    29 /* imcb callback */
     28int jabber_si_send_request(struct im_connection *ic, char *who, struct jabber_transfer *tf );
     29
     30/* file_transfer free() callback */
    3031void jabber_si_free_transfer( file_transfer_t *ft)
    3132{
     
    5051}
    5152
    52 /* imcb callback */
     53/* file_transfer finished() callback */
    5354void jabber_si_finished( file_transfer_t *ft )
    5455{
     
    5859}
    5960
    60 /* imcb callback */
     61/* file_transfer canceled() callback */
    6162void jabber_si_canceled( file_transfer_t *ft, char *reason )
    6263{
     
    7677        xt_free_node( reply );
    7778
     79}
     80
     81void jabber_si_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who )
     82{
     83        struct jabber_transfer *tf;
     84        struct jabber_data *jd = ic->proto_data;
     85
     86        imcb_log( ic, "Incoming file from %s : %s %zd bytes", ic->irc->nick, ft->file_name, ft->file_size );
     87
     88        tf = g_new0( struct jabber_transfer, 1 );
     89
     90        tf->ic = ic;
     91        tf->ft = ft;
     92        tf->ft->data = tf;
     93        tf->ft->free = jabber_si_free_transfer;
     94        tf->ft->finished = jabber_si_finished;
     95        ft->write = jabber_bs_send_write;
     96
     97        jd->filetransfers = g_slist_prepend( jd->filetransfers, tf );
     98
     99        jabber_si_send_request( ic, who, tf );
     100
     101        imcb_file_recv_start( ft );
    78102}
    79103
     
    136160                                break;
    137161                        }
     162
     163                if ( !requestok )
     164                        imcb_log( ic, "WARNING: Unsupported file transfer request from %s", ini_jid);
    138165        }
    139166       
     
    160187
    161188                *s = '/';
    162         } else
    163                 imcb_log( ic, "WARNING: Unsupported file transfer request from %s", ini_jid);
     189        }
    164190
    165191        if ( !requestok )
     
    245271        xt_free_node( reply );
    246272}
     273
     274static xt_status jabber_si_handle_response(struct im_connection *ic, struct xt_node *node, struct xt_node *orig )
     275{
     276        struct xt_node *c, *d;
     277        char *ini_jid, *tgt_jid;
     278        GSList *tflist;
     279        struct jabber_transfer *tf=NULL;
     280        struct jabber_data *jd = ic->proto_data;
     281        char *sid;
     282
     283        if( !( tgt_jid = xt_find_attr( node, "from" ) ) ||
     284            !( ini_jid = xt_find_attr( node, "to" ) ) )
     285        {
     286                imcb_log( ic, "Invalid SI response from=%s to=%s", tgt_jid, ini_jid );
     287                return XT_HANDLED;
     288        }
     289       
     290        imcb_log( ic, "GOT RESPONSE TO FILE" );
     291        /* All this means we expect something like this: ( I think )
     292         * <iq from=... to=...>
     293         *      <si xmlns=si>
     294         *              <file xmlns=ft/>
     295         *              <feature xmlns=feature>
     296         *                      <x xmlns=xdata type=submit>
     297         *                              <field var=stream-method>
     298         *                                      <value>
     299         */
     300        if( !( tgt_jid = xt_find_attr( node, "from" ) ) ||
     301            !( ini_jid = xt_find_attr( node, "to" ) ) ||
     302            !( c = xt_find_node( node->children, "si" ) ) ||
     303            !( strcmp( xt_find_attr( c, "xmlns" ), XMLNS_SI ) == 0 ) ||
     304            !( sid = xt_find_attr( c, "id" ) )||
     305            !( d = xt_find_node( c->children, "file" ) ) ||
     306            !( strcmp( xt_find_attr( d, "xmlns" ), XMLNS_FILETRANSFER ) == 0 ) ||
     307            !( d = xt_find_node( c->children, "feature" ) ) ||
     308            !( strcmp( xt_find_attr( d, "xmlns" ), XMLNS_FEATURE ) == 0 ) ||
     309            !( d = xt_find_node( d->children, "x" ) ) ||
     310            !( strcmp( xt_find_attr( d, "xmlns" ), XMLNS_XDATA ) == 0 ) ||
     311            !( strcmp( xt_find_attr( d, "type" ), "submit" ) == 0 ) ||
     312            !( d = xt_find_node( d->children, "field" ) ) ||
     313            !( strcmp( xt_find_attr( d, "var" ), "stream-method" ) == 0 ) ||
     314            !( d = xt_find_node( d->children, "value" ) ) )
     315        {
     316                imcb_log( ic, "WARNING: Received incomplete Stream Initiation response" );
     317                return XT_HANDLED;
     318        }
     319
     320        if( !( strcmp( d->text, XMLNS_BYTESTREAMS ) == 0 ) ) {
     321                /* since we should only have advertised what we can do and the peer should
     322                 * only have chosen what we offered, this should never happen */
     323                imcb_log( ic, "WARNING: Received invalid Stream Initiation response, method %s", d->text );
     324                       
     325                return XT_HANDLED;
     326        }
     327       
     328        /* Let's see if we can find out what this bytestream should be for... */
     329
     330        for( tflist = jd->filetransfers ; tflist; tflist = g_slist_next(tflist) )
     331        {
     332                struct jabber_transfer *tft = tflist->data;
     333                if( ( strcmp( tft->sid, sid ) == 0 ) )
     334                {
     335                        tf = tft;
     336                        break;
     337                }
     338        }
     339
     340        if (!tf)
     341        {
     342                imcb_log( ic, "WARNING: Received bytestream request from %s that doesn't match an SI request", ini_jid );
     343                return XT_HANDLED;
     344        }
     345
     346        tf->ini_jid = g_strdup( ini_jid );
     347        tf->tgt_jid = g_strdup( tgt_jid );
     348
     349        jabber_bs_send_start( tf );
     350
     351        return XT_HANDLED;
     352}
     353
     354int jabber_si_send_request(struct im_connection *ic, char *who, struct jabber_transfer *tf )
     355{
     356        struct xt_node *node, *sinode;
     357        struct jabber_buddy *bud;
     358
     359        /* who knows how many bits the future holds :) */
     360        char filesizestr[ 1 + ( int ) ( 0.301029995663981198f * sizeof( size_t ) * 8 ) ];
     361
     362        const char *methods[] =
     363        {       
     364                XMLNS_BYTESTREAMS,
     365                //XMLNS_IBB,
     366                NULL
     367        };
     368        const char **m;
     369        char *s;
     370
     371        /* Maybe we should hash this? */
     372        tf->sid = g_strdup_printf( "BitlBeeJabberSID%d", tf->ft->local_id );
     373       
     374        if( ( s = strchr( who, '=' ) ) && jabber_chat_by_name( ic, s + 1 ) )
     375                bud = jabber_buddy_by_ext_jid( ic, who, 0 );
     376        else
     377                bud = jabber_buddy_by_jid( ic, who, 0 );
     378
     379        /* start with the SI tag */
     380        sinode = xt_new_node( "si", NULL, NULL );
     381        xt_add_attr( sinode, "xmlns", XMLNS_SI );
     382        xt_add_attr( sinode, "profile", XMLNS_FILETRANSFER );
     383        xt_add_attr( sinode, "id", tf->sid );
     384
     385/*      if( mimetype )
     386                xt_add_attr( node, "mime-type", mimetype ); */
     387
     388        /* now the file tag */
     389/*      if( desc )
     390                node = xt_new_node( "desc", descr, NULL ); */
     391        node = xt_new_node( "range", NULL, NULL );
     392
     393        sprintf( filesizestr, "%zd", tf->ft->file_size );
     394        node = xt_new_node( "file", NULL, node );
     395        xt_add_attr( node, "xmlns", XMLNS_FILETRANSFER );
     396        xt_add_attr( node, "name", tf->ft->file_name );
     397        xt_add_attr( node, "size", filesizestr );
     398/*      if (hash)
     399                xt_add_attr( node, "hash", hash );
     400        if (date)
     401                xt_add_attr( node, "date", date ); */
     402
     403        xt_add_child( sinode, node );
     404
     405        /* and finally the feature tag */
     406        node = xt_new_node( "field", NULL, NULL );
     407        xt_add_attr( node, "var", "stream-method" );
     408        xt_add_attr( node, "type", "list-single" );
     409
     410        for ( m = methods ; *m ; m ++ )
     411                xt_add_child( node, xt_new_node( "option", NULL, xt_new_node( "value", (char *)*m, NULL ) ) );
     412
     413        node = xt_new_node( "x", NULL, node );
     414        xt_add_attr( node, "xmlns", XMLNS_XDATA );
     415        xt_add_attr( node, "type", "form" );
     416
     417        node = xt_new_node( "feature", NULL, node );
     418        xt_add_attr( node, "xmlns", XMLNS_FEATURE );
     419
     420        xt_add_child( sinode, node );
     421
     422        /* and we are there... */
     423        node = jabber_make_packet( "iq", "set", bud ? bud->full_jid : who, sinode );
     424        jabber_cache_add( ic, node, jabber_si_handle_response );
     425       
     426        return jabber_write_packet( ic, node );
     427}
Note: See TracChangeset for help on using the changeset viewer.