Changeset 1607


Ignore:
Timestamp:
Mar 30, 2007, 12:12:39 AM (15 years ago)
Author:
joshe
Message:

Add iterator function for bencoded lists.

Location:
trunk/libtransmission
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/bencode.c

    r1606 r1607  
    2525#include "transmission.h"
    2626
    27 #define LIST_SIZE   20
     27/* setting to 1 to help expose bugs with tr_bencListAdd and tr_bencDictAdd */
     28#define LIST_SIZE   20 /* number of items to increment list/dict buffer by */
    2829
    2930static int makeroom( benc_val_t * val, int count )
    3031{
    31     int len;
     32    int    len;
    3233    void * new;
    3334
    3435    assert( TYPE_LIST == val->type || TYPE_DICT == val->type );
    3536
    36     len = val->val.l.alloc;
    37     while( val->val.l.count + count >= len )
    38     {
    39         len += LIST_SIZE;
    40     }
    41 
    42     if( len > val->val.l.alloc )
    43     {
    44         /* We need a bigger boat */
    45         new = realloc( val->val.l.vals, len * sizeof( benc_val_t ) );
    46         if( NULL == new )
    47         {
    48             return 1;
    49         }
    50         val->val.l.alloc = len;
    51         val->val.l.vals = new;
    52     }
     37    if( val->val.l.count + count <= val->val.l.alloc )
     38    {
     39        return 1;
     40    }
     41
     42    /* We need a bigger boat */
     43
     44    len = val->val.l.alloc + count + ( count % LIST_SIZE ? 0 : LIST_SIZE );
     45    new = realloc( val->val.l.vals, len * sizeof( benc_val_t ) );
     46    if( NULL == new )
     47    {
     48        return 1;
     49    }
     50
     51    val->val.l.alloc = len;
     52    val->val.l.vals  = new;
    5353
    5454    return 0;
     
    7070    }
    7171
    72     val->begin = buf;
    73 
    7472    if( buf[0] == 'i' )
    7573    {
     74        int64_t num;
     75
    7676        e = memchr( &buf[1], 'e', len - 1 );
    7777        if( NULL == e )
     
    8181
    8282        /* Integer: i1242e */
    83         val->type  = TYPE_INT;
    84         *e         = '\0';
    85         val->val.i = strtoll( &buf[1], &p, 10 );
    86         *e         = 'e';
     83        *e = '\0';
     84        num = strtoll( &buf[1], &p, 10 );
     85        *e = 'e';
    8786
    8887        if( p != e )
     
    9190        }
    9291
     92        tr_bencInitInt( val, num );
    9393        val->end = p + 1;
    9494    }
     
    103103        char   str_expected;
    104104
    105         is_dict          = ( buf[0] == 'd' );
    106         val->type        = is_dict ? TYPE_DICT : TYPE_LIST;
    107         val->val.l.alloc = LIST_SIZE;
    108         val->val.l.count = 0;
    109         val->val.l.vals  = malloc( LIST_SIZE * sizeof( benc_val_t ) );
    110         cur              = &buf[1];
    111         str_expected     = 1;
     105        is_dict      = ( buf[0] == 'd' );
     106        cur          = &buf[1];
     107        str_expected = 1;
     108        tr_bencInit( val, ( is_dict ? TYPE_DICT : TYPE_LIST ) );
    112109        while( cur - buf < len && cur[0] != 'e' )
    113110        {
     
    141138    else
    142139    {
     140        int    slen;
     141        char * sbuf;
     142
    143143        e = memchr( buf, ':', len );
    144144        if( NULL == e )
     
    148148
    149149        /* String: 12:whateverword */
    150         val->type    = TYPE_STR;
    151         e[0]         = '\0';
    152         val->val.s.i = strtol( buf, &p, 10 );
    153         e[0]         = ':';
    154 
    155         if( p != e || 0 > val->val.s.i ||
    156             val->val.s.i > len - ((p + 1) - buf) )
    157         {
    158             return 1;
    159         }
    160 
    161         val->val.s.s               = malloc( val->val.s.i + 1 );
    162         val->val.s.s[val->val.s.i] = 0;
    163         memcpy( val->val.s.s, p + 1, val->val.s.i );
     150        e[0] = '\0';
     151        slen = strtol( buf, &p, 10 );
     152        e[0] = ':';
     153
     154        if( p != e || 0 > slen || len - ( ( p + 1 ) - buf ) < slen )
     155        {
     156            return 1;
     157        }
     158
     159        sbuf = malloc( slen + 1 );
     160        if( NULL == sbuf )
     161        {
     162            return 1;
     163        }
     164
     165        memcpy( sbuf, p + 1, slen );
     166        sbuf[slen] = '\0';
     167        tr_bencInitStr( val, sbuf, slen, 0 );
    164168
    165169        val->end = p + 1 + val->val.s.i;
    166170    }
    167171
     172    val->begin = buf;
    168173    *end = val->end;
    169174
     
    239244benc_val_t * tr_bencDictFind( benc_val_t * val, const char * key )
    240245{
    241     int i;
     246    int len, i;
     247
    242248    if( val->type != TYPE_DICT )
    243249    {
    244250        return NULL;
    245251    }
     252
     253    len = strlen( key );
    246254   
    247255    for( i = 0; i < val->val.l.count; i += 2 )
    248256    {
    249         if( !strcmp( val->val.l.vals[i].val.s.s, key ) )
     257        if( TYPE_STR != val->val.l.vals[i].type ||
     258            len != val->val.l.vals[i].val.s.i )
     259        {
     260            continue;
     261        }
     262        if( 0 == memcmp(val->val.l.vals[i].val.s.s, key, len ) )
    250263        {
    251264            return &val->val.l.vals[i+1];
     
    274287
    275288    return ret;
     289}
     290
     291benc_val_t * tr_bencListIter( benc_val_t * list, int * pos )
     292{
     293    assert( TYPE_LIST == list->type );
     294
     295    if( NULL == list->val.l.vals )
     296    {
     297        return NULL;
     298    }
     299
     300    if( 0 > *pos )
     301    {
     302        *pos = 0;
     303    }
     304
     305    if( list->val.l.count <= *pos )
     306    {
     307        return NULL;
     308    }
     309
     310    (*pos)++;
     311
     312    return &list->val.l.vals[ (*pos) - 1 ];
    276313}
    277314
  • trunk/libtransmission/bencode.h

    r1606 r1607  
    6161benc_val_t * tr_bencDictFindFirst( benc_val_t * val, ... );
    6262
     63benc_val_t * tr_bencListIter( benc_val_t * list, int * pos );
     64
    6365/* marks a string as 'do not free' and returns it */
    6466char *       tr_bencStealStr( benc_val_t * val );
  • trunk/libtransmission/metainfo.c

    r1590 r1607  
    3737                        const uint8_t * buf, size_t buflen );
    3838static int getfile( char * buf, int size,
    39                     const char * prefix, const benc_val_t * name );
     39                    const char * prefix, benc_val_t * name );
    4040static int getannounce( tr_info_t * inf, benc_val_t * meta );
    4141static char * announceToScrape( const char * announce );
     42static int parseFiles( tr_info_t * inf, benc_val_t * name,
     43                       benc_val_t * files, benc_val_t * length );
    4244static void strcatUTF8( char *, int, const char *, int );
    4345
     
    5153{
    5254    char       * buf;
    53     benc_val_t   meta, * beInfo, * list, * val, * val2;
     55    benc_val_t   meta, * beInfo, * val, * val2;
    5456    int          i;
    5557    size_t       len;
     
    174176    /* get file or top directory name */
    175177    val = tr_bencDictFindFirst( beInfo, "name.utf-8", "name", NULL );
    176     if( NULL == val || TYPE_STR != val->type )
    177     {
    178         tr_err( "%s \"name\" string", ( val ? "Invalid" : "Missing" ) );
     178    if( parseFiles( inf, tr_bencDictFindFirst( beInfo,
     179                                               "name.utf-8", "name", NULL ),
     180                    tr_bencDictFind( beInfo, "files" ),
     181                    tr_bencDictFind( beInfo, "length" ) ) )
     182    {
    179183        goto fail;
    180     }
    181     strcatUTF8( inf->name, sizeof( inf->name ), val->val.s.s, 1 );
    182     if( '\0' == inf->name[0] )
    183     {
    184         tr_err( "Invalid \"name\" string" );
    185         goto fail;
    186     }
    187     inf->totalSize = 0;
    188 
    189     if( ( list = tr_bencDictFind( beInfo, "files" ) ) )
    190     {
    191         /* Multi-file mode */
    192         inf->multifile = 1;
    193         inf->fileCount = list->val.l.count;
    194         inf->files     = calloc( inf->fileCount, sizeof( tr_file_t ) );
    195 
    196         for( i = 0; i < list->val.l.count; i++ )
    197         {
    198             val = tr_bencDictFindFirst( &list->val.l.vals[i],
    199                                         "path.utf-8", "path", NULL );
    200             if( getfile( inf->files[i].name, sizeof( inf->files[i].name ),
    201                          inf->name, val ) )
    202             {
    203                 tr_err( "%s \"path\" entry", ( val ? "Invalid" : "Missing" ) );
    204                 goto fail;
    205             }
    206             val = tr_bencDictFind( &list->val.l.vals[i], "length" );
    207             inf->files[i].length  = val->val.i;
    208             inf->totalSize       += val->val.i;
    209         }
    210     }
    211     else
    212     {
    213         /* Single-file mode */
    214         inf->multifile = 0;
    215         inf->fileCount = 1;
    216         inf->files     = calloc( sizeof( tr_file_t ), 1 );
    217 
    218         strcatUTF8( inf->files[0].name, sizeof( inf->files[0].name),
    219                     val->val.s.s, 1 );
    220        
    221         val = tr_bencDictFind( beInfo, "length" );
    222         if( NULL == val || TYPE_INT != val->type )
    223         {
    224             tr_err( "%s \"length\" entry", ( val ? "Invalid" : "Missing" ) );
    225             goto fail;
    226         }
    227         inf->files[0].length  = val->val.i;
    228         inf->totalSize       += val->val.i;
    229184    }
    230185
     
    272227
    273228static int getfile( char * buf, int size,
    274                     const char * prefix, const benc_val_t * name )
    275 {
    276     const benc_val_t * dir;
    277     const char      ** list;
    278     int                ii, jj;
     229                    const char * prefix, benc_val_t * name )
     230{
     231    benc_val_t * dir;
     232    const char ** list;
     233    int           ii, jj;
    279234
    280235    if( TYPE_LIST != name->type )
     
    289244    }
    290245
    291     for( ii = jj = 0; name->val.l.count > ii; ii++ )
    292     {
    293         if( TYPE_STR != name->val.l.vals[ii].type )
     246    ii = jj = 0;
     247    while( NULL != ( dir = tr_bencListIter( name, &ii ) ) )
     248    {
     249        if( TYPE_STR != dir->type )
    294250        {
    295251            continue;
    296252        }
    297         dir = &name->val.l.vals[ii];
    298253        if( 0 == strcmp( "..", dir->val.s.s ) )
    299254        {
     
    328283static int getannounce( tr_info_t * inf, benc_val_t * meta )
    329284{
    330     benc_val_t              * val, * subval, * urlval;
    331     char                    * address, * announce;
    332     int                       ii, jj, port, random;
     285    benc_val_t        * val, * subval, * urlval;
     286    char              * address, * announce;
     287    int                 ii, jj, port, random, subcount;
    333288    tr_tracker_info_t * sublist;
    334     int subcount;
    335289    void * swapping;
    336290
     
    344298
    345299        /* iterate through the announce-list's tiers */
    346         for( ii = 0; ii < val->val.l.count; ii++ )
    347         {
    348             subval = &val->val.l.vals[ii];
     300        ii = 0;
     301        while( NULL != ( subval = tr_bencListIter( val, &ii ) ) )
     302        {
    349303            if( TYPE_LIST != subval->type || 0 >= subval->val.l.count )
    350304            {
     
    355309
    356310            /* iterate through the tier's items */
    357             for( jj = 0; jj < subval->val.l.count; jj++ )
     311            jj = 0;
     312            while( NULL != ( urlval = tr_bencListIter( subval, &jj ) ) )
    358313            {
    359                 urlval = &subval->val.l.vals[jj];
    360314                if( TYPE_STR != urlval->type ||
    361315                    tr_httpParseUrl( urlval->val.s.s, urlval->val.s.i,
     
    378332            }
    379333
    380             /* just use sublist as is if it's full */
     334            /* just use sublist as-is if it's full */
    381335            if( subcount == subval->val.l.count )
    382336            {
     
    622576}
    623577
     578int
     579parseFiles( tr_info_t * inf, benc_val_t * name,
     580            benc_val_t * files, benc_val_t * length )
     581{
     582    benc_val_t * item, * path;
     583    int ii;
     584
     585    if( NULL == name || TYPE_STR != name->type )
     586    {
     587        tr_err( "%s \"name\" string", ( name ? "Invalid" : "Missing" ) );
     588        return 1;
     589    }
     590
     591    strcatUTF8( inf->name, sizeof( inf->name ), name->val.s.s, 1 );
     592    if( '\0' == inf->name[0] )
     593    {
     594        tr_err( "Invalid \"name\" string" );
     595        return 1;
     596    }
     597    inf->totalSize = 0;
     598
     599    if( files && TYPE_LIST == files->type )
     600    {
     601        /* Multi-file mode */
     602        inf->multifile = 1;
     603        inf->fileCount = files->val.l.count;
     604        inf->files     = calloc( inf->fileCount, sizeof( inf->files[0] ) );
     605
     606        if( NULL == inf->files )
     607        {
     608            return 1;
     609        }
     610
     611        item = NULL;
     612        ii   = 0;
     613        while( NULL != ( item = tr_bencListIter( files, &ii ) ) )
     614        {
     615            path = tr_bencDictFindFirst( item, "path.utf-8", "path", NULL );
     616            if( getfile( inf->files[ii-1].name, sizeof( inf->files[ii-1].name ),
     617                         inf->name, path ) )
     618            {
     619                tr_err( "%s \"path\" entry",
     620                        ( path ? "Invalid" : "Missing" ) );
     621                return 1;
     622            }
     623            length = tr_bencDictFind( item, "length" );
     624            if( NULL == length || TYPE_INT != length->type )
     625            {
     626                tr_err( "%s \"length\" entry",
     627                        ( length ? "Invalid" : "Missing" ) );
     628                return 1;
     629            }
     630            inf->files[ii-1].length = length->val.i;
     631            inf->totalSize         += length->val.i;
     632        }
     633    }
     634    else if( NULL != length && TYPE_INT == length->type )
     635    {
     636        /* Single-file mode */
     637        inf->multifile = 0;
     638        inf->fileCount = 1;
     639        inf->files     = calloc( 1, sizeof( inf->files[0] ) );
     640
     641        if( NULL == inf->files )
     642        {
     643            return 1;
     644        }
     645
     646        strcatUTF8( inf->files[0].name, sizeof( inf->files[0].name ),
     647                    name->val.s.s, 1 );
     648
     649        inf->files[0].length = length->val.i;
     650        inf->totalSize      += length->val.i;
     651    }
     652    else
     653    {
     654        tr_err( "%s \"files\" entry and %s \"length\" entry",
     655                ( files ? "Invalid" : "Missing" ),
     656                ( length ? "invalid" : "missing" ) );
     657    }
     658
     659    return 0;
     660}
     661
    624662/***********************************************************************
    625663 * strcatUTF8
  • trunk/libtransmission/peeraz.h

    r1606 r1607  
    383383    /* fill bitmask with supported message info */
    384384    msgs = tr_bitfieldNew( azmsgCount() );
    385     for( ii = 0; ii < sub->val.l.count; ii++ )
    386     {
    387         dict = &sub->val.l.vals[ii];
     385    ii = -1;
     386    while( NULL != ( dict = tr_bencListIter( sub, &ii ) ) )
     387    {
    388388        if( TYPE_DICT != dict->type )
    389389        {
     
    476476    }
    477477
    478     used = 0;
    479     for( ii = 0; ii < list->val.l.count; ii++ )
    480     {
    481         pair = &list->val.l.vals[ii];
     478    ii = used = 0;
     479    while( NULL != ( pair = tr_bencListIter( list, &ii ) ) )
     480    {
    482481        if( TYPE_STR == pair->type && 6 == pair->val.s.i )
    483482        {
  • trunk/libtransmission/tracker.c

    r1596 r1607  
    9595static void        killHttp         ( tr_http_t ** http );
    9696static int         shouldChangePort( tr_tracker_t * tc );
     97static uint8_t *   parseOriginalPeers( benc_val_t * bePeers, int * peerCount );
    9798
    9899tr_tracker_t * tr_trackerInit( tr_torrent_t * tor )
     
    794795    }
    795796
    796     if( bePeers->type & TYPE_LIST )
     797    if( TYPE_LIST == bePeers->type )
    797798    {
    798799        /* Original protocol */
    799800        if( bePeers->val.l.count > 0 )
    800801        {
    801             struct in_addr addr;
    802             in_port_t port;
    803 
    804             peerCount = 0;
    805             peerCompact = malloc( 6 * bePeers->val.l.count );
    806 
    807             /* Convert to compact form */
    808             for( i = 0; i < bePeers->val.l.count; i++ )
    809             {
    810                 if( !( beFoo = tr_bencDictFind(
    811                     &bePeers->val.l.vals[i], "ip" ) ) )
    812                     continue;
    813                 if( tr_netResolve( beFoo->val.s.s, &addr ) )
    814                     continue;
    815                 memcpy( &peerCompact[6 * peerCount], &addr, 4 );
    816 
    817                 if( !( beFoo = tr_bencDictFind(
    818                     &bePeers->val.l.vals[i], "port" ) ) )
    819                     continue;
    820                 port = htons( beFoo->val.i );
    821                 memcpy( &peerCompact[6 * peerCount + 4], &port, 2 );
    822 
    823                 peerCount++;
    824             }
    825         }
    826     }
    827     else if( bePeers->type & TYPE_STR )
     802            peerCompact = parseOriginalPeers( bePeers, &peerCount );
     803        }
     804    }
     805    else if( TYPE_STR == bePeers->type )
    828806    {
    829807        /* "Compact" extension */
     
    11021080    return ( tor->publicPort != tc->publicPort );
    11031081}
     1082
     1083/* Convert to compact form */
     1084static uint8_t *
     1085parseOriginalPeers( benc_val_t * bePeers, int * peerCount )
     1086{
     1087    struct in_addr addr;
     1088    in_port_t      port;
     1089    uint8_t      * peerCompact;
     1090    benc_val_t   * peer, * addrval, * portval;
     1091    int            ii, count;
     1092
     1093    assert( TYPE_LIST == bePeers->type );
     1094
     1095    count  = 0;
     1096    peerCompact = malloc( 6 * bePeers->val.l.count );
     1097    if( NULL == peerCompact )
     1098    {
     1099        return NULL;
     1100    }
     1101
     1102    ii = -1;
     1103    while( NULL != ( peer = tr_bencListIter( bePeers, &ii ) ) )
     1104    {
     1105        addrval = tr_bencDictFind( peer, "ip" );
     1106        if( NULL == addrval || TYPE_STR != addrval->type ||
     1107            tr_netResolve( addrval->val.s.s, &addr ) )
     1108        {
     1109            continue;
     1110        }
     1111        memcpy( &peerCompact[6 * count], &addr, 4 );
     1112
     1113        portval = tr_bencDictFind( peer, "port" );
     1114        if( NULL == portval || TYPE_INT != portval->type ||
     1115            0 > portval->val.i || 0xffff < portval->val.i )
     1116        {
     1117            continue;
     1118        }
     1119        port = htons( portval->val.i );
     1120        memcpy( &peerCompact[6 * count + 4], &port, 2 );
     1121
     1122        count++;
     1123    }
     1124
     1125    *peerCount = count;
     1126
     1127    return peerCompact;
     1128}
Note: See TracChangeset for help on using the changeset viewer.