Changeset 8154


Ignore:
Timestamp:
Apr 5, 2009, 5:52:21 PM (12 years ago)
Author:
charles
Message:

(trunk) Use proper notation for json floating-point and bool types. For backwards compatability, still allow old-style printf strings as doubles, and 0s and 1s as bools.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/doc/rpc-spec.txt

    r8148 r8154  
    1313
    14142.  Message Format
    15 
    16    Messages are formatted in a subset of JSON easily represented
    17    as bencoded data.  Arrays, objects, strings, and whole numbers
    18    all have one-to-one mappings between JSON and benc.
    19 
    20    Booleans and floating-point numbers are also used in the JSON messages.
    21    Those two types aren't native to benc, so they're encoded this way:
    22    Booleans are encoded as numbers where 0 is false and 1 is true.
    23    Floating-point numbers are represented as strings.
    2415
    2516   Messages are formatted as objects.  There are two types:
     
    9990   ----------------------------------+-------------------------------------------------
    10091   "downloadLimit"                   | number     maximum download speed (in K/s)
    101    "downloadLimited"                 | 'boolean'  true if "downloadLimit" is honored
     92   "downloadLimited"                 | boolean    true if "downloadLimit" is honored
    10293   "files-wanted"                    | array      indices of file(s) to download
    10394   "files-unwanted"                  | array      indices of file(s) to not download
    104    "honorsSessionLimits"             | 'boolean'  true if session upload limits are honored
     95   "honorsSessionLimits"             | boolean    true if session upload limits are honored
    10596   "ids"                             | array      torrent list, as described in 3.1
    10697   "peer-limit"                      | number     maximum number of peers
     
    10899   "priority-low"                    | array      indices of low-priority file(s)
    109100   "priority-normal"                 | array      indices of normal-priority file(s)
    110    "seedRatioLimit"                  | 'double'   session seeding ratio
     101   "seedRatioLimit"                  | double     session seeding ratio
    111102   "seedRatioMode"                   | number     which ratio to use.  See tr_ratiolimit
    112103   "uploadLimit"                     | number     maximum upload speed (in K/s)
    113    "uploadLimited"                   | 'boolean'  true if "uploadLimit" is honored
     104   "uploadLimited"                   | boolean    true if "uploadLimit" is honored
    114105
    115106   Just as an empty "ids" value is shorthand for "all ids", using an empty array
     
    152143   downloaders                     | number                      | tr_stat
    153144   downloadLimit                   | number                      | tr_torrent
    154    downloadLimited                 | 'boolean'                   | tr_torrent
     145   downloadLimited                 | boolean                     | tr_torrent
    155146   error                           | number                      | tr_stat
    156147   errorString                     | number                      | tr_stat
     
    161152   haveUnchecked                   | number                      | tr_stat
    162153   haveValid                       | number                      | tr_stat
    163    honorsSessionLimits             | 'boolean'                   | tr_torrent
     154   honorsSessionLimits             | boolean                     | tr_torrent
    164155   id                              | number                      | tr_torrent
    165    isPrivate                       | 'boolean'                   | tr_torrent
     156   isPrivate                       | boolean                     | tr_torrent
    166157   lastAnnounceTime                | number                      | tr_stat
    167158   lastScrapeTime                  | number                      | tr_stat
     
    180171   peersKnown                      | number                      | tr_stat
    181172   peersSendingToUs                | number                      | tr_stat
    182    percentDone                     | 'double'                    | tr_stat
     173   percentDone                     | double                      | tr_stat
    183174   pieces                          | string (see below)          | tr_torrent
    184175   pieceCount                      | tnumber                     | tr_info
    185176   pieceSize                       | tnumber                     | tr_info
    186177   priorities                      | array (see below)           | n/a
    187    ratio                           | 'double'                    | tr_stat
     178   ratio                           | double                      | tr_stat
    188179   rateDownload (B/s)              | number                      | tr_stat
    189180   rateUpload (B/s)                | number                      | tr_stat
    190    recheckProgress                 | 'double'                    | tr_stat
     181   recheckProgress                 | double                      | tr_stat
    191182   scrapeResponse                  | string                      | tr_stat
    192183   scrapeURL                       | string                      | tr_stat
    193184   seeders                         | number                      | tr_stat
    194    seedRatioLimit                  | 'double'                    | tr_torrent
     185   seedRatioLimit                  | double                      | tr_torrent
    195186   seedRatioMode                   | number                      | tr_ratiolimit
    196187   sizeWhenDone                    | number                      | tr_stat
     
    204195   uploadedEver                    | number                      | tr_stat
    205196   uploadLimit                     | number                      | tr_torrent
    206    uploadLimited                   | 'boolean'                   | tr_torrent
    207    uploadRatio                     | 'double'                    | tr_stat
     197   uploadLimited                   | boolean                     | tr_torrent
     198   uploadRatio                     | double                      | tr_stat
    208199   wanted                          | array (see below)           | n/a
    209200   webseeds                        | array (see below)           | n/a
     
    224215                          +-------------------------+------------+
    225216                          | bytesCompleted          | number     | tr_torrent
    226                           | wanted                  | 'boolean'  | tr_info
     217                          | wanted                  | boolean    | tr_info
    227218                          | priority                | number     | tr_info
    228219   -----------------------+--------------------------------------+
     
    231222                          | address                 | string     | tr_peer_stat
    232223                          | clientName              | string     | tr_peer_stat
    233                           | clientIsChoked          | 'boolean'  | tr_peer_stat
    234                           | clientIsInterested      | 'boolean'  | tr_peer_stat
    235                           | isDownloadingFrom       | 'boolean'  | tr_peer_stat
    236                           | isEncrypted             | 'boolean'  | tr_peer_stat
    237                           | isIncoming              | 'boolean'  | tr_peer_stat
    238                           | isUploadingTo           | 'boolean'  | tr_peer_stat
    239                           | peerIsChoked            | 'boolean'  | tr_peer_stat
    240                           | peerIsInterested        | 'boolean'  | tr_peer_stat
     224                          | clientIsChoked          | boolean    | tr_peer_stat
     225                          | clientIsInterested      | boolean    | tr_peer_stat
     226                          | isDownloadingFrom       | boolean    | tr_peer_stat
     227                          | isEncrypted             | boolean    | tr_peer_stat
     228                          | isIncoming              | boolean    | tr_peer_stat
     229                          | isUploadingTo           | boolean    | tr_peer_stat
     230                          | peerIsChoked            | boolean    | tr_peer_stat
     231                          | peerIsInterested        | boolean    | tr_peer_stat
    241232                          | port                    | number     | tr_peer_stat
    242                           | progress                | 'double'   | tr_peer_stat
     233                          | progress                | double     | tr_peer_stat
    243234                          | rateToClient (B/s)      | number     | tr_peer_stat
    244235                          | rateToPeer (B/s)        | number     | tr_peer_stat
     
    324315   "filename"         | string      filename or URL of the .torrent file
    325316   "metainfo"         | string      base64-encoded .torrent content
    326    "paused"           | 'boolean'   if true, don't start the torrent
     317   "paused"           | boolean     if true, don't start the torrent
    327318   "peer-limit"       | number      maximum number of peers
    328319   "files-wanted"     | array       indices of file(s) to download
     
    348339   ---------------------------+-------------------------------------------------
    349340   "ids"                      | array      torrent list, as described in 3.1
    350    "delete-local-data"        | 'boolean'  delete local data. (default: false)
     341   "delete-local-data"        | boolean    delete local data. (default: false)
    351342
    352343   Response arguments: none
     
    360351   ---------------------------+-------------------------------------------------
    361352   "alt-speed-down"           | number     max global download speed (in K/s)
    362    "alt-speed-enabled"        | 'boolean'  true means use the alt speeds
     353   "alt-speed-enabled"        | boolean    true means use the alt speeds
    363354   "alt-speed-time-begin"     | number     when to turn on alt speeds (units: minutes after midnight)
    364    "alt-speed-time-enabled"   | 'boolean'  true means the scheduled on/off times are used
     355   "alt-speed-time-enabled"   | boolean    true means the scheduled on/off times are used
    365356   "alt-speed-time-end"       | number     when to turn off alt speeds (units: same)
    366357   "alt-speed-time-day"       | number     what day(s) to turn on alt speeds (look at tr_sched_day)
    367358   "alt-speed-up"             | number     max global upload speed (in K/s)
    368    "blocklist-enabled"        | 'boolean'  true means enabled
     359   "blocklist-enabled"        | boolean    true means enabled
    369360   "blocklist-size"           | number     number of rules in the blocklist
    370361   "encryption"               | string     "required", "preferred", "tolerated"
     
    372363   "peer-limit-global"        | number     maximum global number of peers
    373364   "peer-limit-per-torrent"   | number     maximum global number of peers
    374    "pex-enabled"              | 'boolean'  true means allow pex in public torrents
     365   "pex-enabled"              | boolean    true means allow pex in public torrents
    375366   "peer-port"                | number     port number
    376    "peer-port-random-on-start"| 'boolean'  true means pick a random peer port on launch
    377    "port-forwarding-enabled"  | 'boolean'  true means enabled
     367   "peer-port-random-on-start"| boolean    true means pick a random peer port on launch
     368   "port-forwarding-enabled"  | boolean    true means enabled
    378369   "rpc-version"              | number     the current RPC API version
    379370   "rpc-version-minimum"      | number     the minimum RPC API version supported
    380    "seedRatioLimit"           | 'double'   the default seed ratio for torrents to use
    381    "seedRatioLimited"         | 'boolean'  true if seedRatioLimit is honored by default
     371   "seedRatioLimit"           | double     the default seed ratio for torrents to use
     372   "seedRatioLimited"         | boolean    true if seedRatioLimit is honored by default
    382373   "speed-limit-down"         | number     max global download speed (in K/s)
    383    "speed-limit-down-enabled" | 'boolean'  true means enabled
     374   "speed-limit-down-enabled" | boolean    true means enabled
    384375   "speed-limit-up"           | number     max global upload speed (in K/s)
    385    "speed-limit-up-enabled"   | 'boolean'  true means enabled
     376   "speed-limit-up-enabled"   | boolean    true means enabled
    386377   "version"                  | string     long version string "$version ($revision)"
    387378
  • trunk/libtransmission/bencode.c

    r8114 r8154  
    415415               int64_t *       setme )
    416416{
    417     const tr_bool success = tr_bencIsInt( val );
    418 
    419     if( success && setme )
    420         *setme = val->val.i;
     417    tr_bool success = FALSE;
     418
     419    if( !success && (( success = tr_bencIsInt( val ))))
     420        if( setme )
     421            *setme = val->val.i;
     422
     423    if( !success && (( success = tr_bencIsBool( val )))) {
     424        fprintf( stderr, "warning: reading bool as an int\n" );
     425        if( setme )
     426            *setme = val->val.b ? 1 : 0;
     427    }
    421428
    422429    return success;
     
    440447    tr_bool success = FALSE;
    441448
     449    if(( success = tr_bencIsBool( val )))
     450        *setme = val->val.b;
     451
    442452    if( !success && tr_bencIsInt( val ) )
    443453        if(( success = ( val->val.i==0 || val->val.i==1 ) ))
     
    455465{
    456466    tr_bool success = FALSE;
     467
     468    if( !success && (( success = tr_bencIsReal( val ))))
     469        *setme = val->val.d;
     470
     471    if( !success && (( success = tr_bencIsInt( val ))))
     472        *setme = val->val.i;
    457473
    458474    if( !success && tr_bencIsString(val) )
     
    473489    }
    474490
    475     if( !success && tr_bencIsInt(val) )
    476     {
    477         success = TRUE;
    478         *setme = val->val.i;
    479     }
    480491
    481492    return success;
     
    599610
    600611void
    601 tr_bencInitInt( tr_benc * val,
    602                 int64_t   num )
    603 {
    604     tr_bencInit( val, TYPE_INT );
    605     val->val.i = num;
     612tr_bencInitBool( tr_benc * b, int value )
     613{
     614    tr_bencInit( b, TYPE_BOOL );
     615    b->val.b = value != 0;
     616}
     617
     618void
     619tr_bencInitReal( tr_benc * b, double value )
     620{
     621    tr_bencInit( b, TYPE_REAL );
     622    b->val.d = value;
     623}
     624
     625void
     626tr_bencInitInt( tr_benc * b, int64_t value )
     627{
     628    tr_bencInit( b, TYPE_INT );
     629    b->val.i = value;
    606630}
    607631
    608632int
    609 tr_bencInitList( tr_benc * val,
    610                  size_t    reserveCount )
    611 {
    612     tr_bencInit( val, TYPE_LIST );
    613     return tr_bencListReserve( val, reserveCount );
     633tr_bencInitList( tr_benc * b, size_t reserveCount )
     634{
     635    tr_bencInit( b, TYPE_LIST );
     636    return tr_bencListReserve( b, reserveCount );
    614637}
    615638
    616639int
    617 tr_bencListReserve( tr_benc * val,
    618                     size_t    count )
    619 {
    620     assert( tr_bencIsList( val ) );
    621     return makeroom( val, count );
     640tr_bencListReserve( tr_benc * b, size_t count )
     641{
     642    assert( tr_bencIsList( b ) );
     643    return makeroom( b, count );
    622644}
    623645
    624646int
    625 tr_bencInitDict( tr_benc * val,
    626                  size_t    reserveCount )
    627 {
    628     tr_bencInit( val, TYPE_DICT );
    629     return tr_bencDictReserve( val, reserveCount );
     647tr_bencInitDict( tr_benc * b, size_t reserveCount )
     648{
     649    tr_bencInit( b, TYPE_DICT );
     650    return tr_bencDictReserve( b, reserveCount );
    630651}
    631652
    632653int
    633 tr_bencDictReserve( tr_benc * val,
    634                     size_t    reserveCount )
    635 {
    636     assert( tr_bencIsDict( val ) );
    637     return makeroom( val, reserveCount * 2 );
     654tr_bencDictReserve( tr_benc * b, size_t reserveCount )
     655{
     656    assert( tr_bencIsDict( b ) );
     657    return makeroom( b, reserveCount * 2 );
    638658}
    639659
     
    717737}
    718738
     739static tr_benc*
     740dictFindOrAdd( tr_benc * dict, const char * key, int type )
     741{
     742    tr_benc * child;
     743
     744    /* see if it already exists, and if so, try to reuse it */
     745    if(( child = tr_bencDictFind( dict, key ))) {
     746        if( !tr_bencIsType( child, type ) ) {
     747            tr_bencDictRemove( dict, key );
     748            child = NULL;
     749        }
     750    }
     751
     752    /* if it doesn't exist, create it */
     753    if( child == NULL )
     754        child = tr_bencDictAdd( dict, key );
     755
     756    return child;
     757}
     758
    719759tr_benc*
    720760tr_bencDictAddInt( tr_benc *    dict,
     
    722762                   int64_t      val )
    723763{
    724     tr_benc * child;
    725 
    726     /* see if it already exists, and if so, try to reuse it */
    727     if(( child = tr_bencDictFind( dict, key ))) {
    728         if( !tr_bencIsInt( child ) ) {
    729             tr_bencDictRemove( dict, key );
    730             child = NULL;
    731         }
    732     }
    733 
    734     /* if it doesn't exist, create it */
    735     if( child == NULL )
    736         child = tr_bencDictAdd( dict, key );
    737 
    738     /* set it */
     764    tr_benc * child = dictFindOrAdd( dict, key, TYPE_INT );
    739765    tr_bencInitInt( child, val );
    740 
    741766    return child;
    742767}
     
    745770tr_bencDictAddBool( tr_benc * dict, const char * key, tr_bool val )
    746771{
    747     assert( tr_isBool( val ) );
    748 
    749     return tr_bencDictAddInt( dict, key, val );
     772    tr_benc * child = dictFindOrAdd( dict, key, TYPE_BOOL );
     773    tr_bencInitBool( child, val );
     774    return child;
     775}
     776
     777tr_benc*
     778tr_bencDictAddReal( tr_benc * dict, const char * key, double val )
     779{
     780    tr_benc * child = dictFindOrAdd( dict, key, TYPE_REAL );
     781    tr_bencInitReal( child, val );
     782    return child;
    750783}
    751784
     
    775808}
    776809
     810#if 0
    777811tr_benc*
    778812tr_bencDictAddReal( tr_benc * dict, const char * key, double d )
    779813{
     814    ccc
    780815    char buf[128];
    781816    char * locale;
     
    790825    return tr_bencDictAddStr( dict, key, buf );
    791826}
     827#endif
    792828
    793829tr_benc*
     
    961997{
    962998    BencWalkFunc    intFunc;
     999    BencWalkFunc    boolFunc;
     1000    BencWalkFunc    realFunc;
    9631001    BencWalkFunc    stringFunc;
    9641002    BencWalkFunc    dictBeginFunc;
     
    10121050                    break;
    10131051
     1052                case TYPE_BOOL:
     1053                    walkFuncs->boolFunc( val, user_data );
     1054                    break;
     1055
     1056                case TYPE_REAL:
     1057                    walkFuncs->realFunc( val, user_data );
     1058                    break;
     1059
    10141060                case TYPE_STR:
    10151061                    walkFuncs->stringFunc( val, user_data );
     
    10521098
    10531099static void
     1100saveBoolFunc( const tr_benc * val, void * evbuf )
     1101{
     1102    evbuffer_add_printf( evbuf, "i%de", val->val.b?1:0 );
     1103}
     1104
     1105static void
     1106saveRealFunc( const tr_benc * val, void * evbuf )
     1107{
     1108    char buf[128];
     1109    char * locale;
     1110    size_t len;
     1111
     1112    /* always use a '.' decimal point s.t. locale-hopping doesn't bite us */
     1113    locale = tr_strdup( setlocale ( LC_NUMERIC, NULL ) );
     1114    setlocale( LC_NUMERIC, "POSIX" );
     1115    tr_snprintf( buf, sizeof( buf ), "%f", val->val.d );
     1116    setlocale( LC_NUMERIC, locale );
     1117    tr_free( locale );
     1118
     1119    len = strlen( buf );
     1120    evbuffer_add_printf( evbuf, "%lu:", (unsigned long)buf );
     1121    evbuffer_add( evbuf, buf, len );
     1122}
     1123
     1124static void
    10541125saveStringFunc( const tr_benc * val,
    10551126                void *          vevbuf )
     
    10911162
    10921163    walkFuncs.intFunc = saveIntFunc;
     1164    walkFuncs.boolFunc = saveBoolFunc;
     1165    walkFuncs.realFunc = saveRealFunc;
    10931166    walkFuncs.stringFunc = saveStringFunc;
    10941167    walkFuncs.dictBeginFunc = saveDictBeginFunc;
     
    11371210
    11381211        walkFuncs.intFunc = freeDummyFunc;
     1212        walkFuncs.boolFunc = freeDummyFunc;
     1213        walkFuncs.realFunc = freeDummyFunc;
    11391214        walkFuncs.stringFunc = freeStringFunc;
    11401215        walkFuncs.dictBeginFunc = freeContainerBeginFunc;
     
    12331308
    12341309    evbuffer_add_printf( data->out, "%" PRId64, val->val.i );
     1310    jsonChildFunc( data );
     1311}
     1312
     1313static void
     1314jsonBoolFunc( const tr_benc * val, void * vdata )
     1315{
     1316    struct jsonWalk * data = vdata;
     1317
     1318    evbuffer_add_printf( data->out, "%s", (val->val.b?"true":"false") );
     1319    jsonChildFunc( data );
     1320}
     1321
     1322static void
     1323jsonRealFunc( const tr_benc * val, void * vdata )
     1324{
     1325    struct jsonWalk * data = vdata;
     1326    char * locale;
     1327
     1328    /* json requires a '.' decimal point regardless of locale */
     1329    locale = tr_strdup( setlocale ( LC_NUMERIC, NULL ) );
     1330    setlocale( LC_NUMERIC, "POSIX" );
     1331    evbuffer_add_printf( data->out, "%f", val->val.d );
     1332    setlocale( LC_NUMERIC, locale );
     1333    tr_free( locale );
     1334
    12351335    jsonChildFunc( data );
    12361336}
     
    13671467
    13681468    walkFuncs.intFunc = jsonIntFunc;
     1469    walkFuncs.boolFunc = jsonBoolFunc;
     1470    walkFuncs.realFunc = jsonRealFunc;
    13691471    walkFuncs.stringFunc = jsonStringFunc;
    13701472    walkFuncs.dictBeginFunc = jsonDictBeginFunc;
  • trunk/libtransmission/bencode.h

    r8112 r8154  
    1414#define TR_BENCODE_H 1
    1515
     16#ifdef __cplusplus
     17extern "C" {
     18#endif
     19
    1620#include <inttypes.h> /* for int64_t */
    1721
     
    2327    TYPE_STR  = 2,
    2428    TYPE_LIST = 4,
    25     TYPE_DICT = 8
     29    TYPE_DICT = 8,
     30    TYPE_BOOL = 16,
     31    TYPE_REAL = 32
    2632};
    2733
     
    3137    union
    3238    {
    33         int64_t i;
    34         struct
     39        uint8_t b; /* bool type */
     40
     41        double d;  /* double type */
     42
     43        int64_t i; /* int type */
     44
     45        struct /* string type */
    3546        {
    3647            size_t i;
    3748            char * s;
    3849        } s;
    39         struct
     50
     51        struct /* list & dict types */
    4052        {
    4153            size_t alloc;
     
    4658} tr_benc;
    4759
    48 #ifdef __cplusplus
    49 extern "C" {
    50 #endif
    51 
    5260/***
    5361****
     
    96104
    97105int       tr_bencInitList( tr_benc *, size_t reserveCount );
     106
     107void      tr_bencInitBool( tr_benc *, int value );
     108
     109void      tr_bencInitReal( tr_benc *, double value );
    98110
    99111/***
     
    173185static TR_INLINE tr_bool tr_bencIsList  ( const tr_benc * b ) { return tr_bencIsType( b, TYPE_LIST ); }
    174186static TR_INLINE tr_bool tr_bencIsString( const tr_benc * b ) { return tr_bencIsType( b, TYPE_STR ); }
     187static TR_INLINE tr_bool tr_bencIsBool  ( const tr_benc * b ) { return tr_bencIsType( b, TYPE_BOOL ); }
     188static TR_INLINE tr_bool tr_bencIsReal  ( const tr_benc * b ) { return tr_bencIsType( b, TYPE_REAL ); }
    175189
    176190/**
Note: See TracChangeset for help on using the changeset viewer.