Changeset 5137


Ignore:
Timestamp:
Feb 27, 2008, 6:01:46 AM (14 years ago)
Author:
charles
Message:

tear out about 1/3 of ipcparse's overhead.

Location:
trunk
Files:
1 added
1 deleted
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/daemon/client.c

    r5127 r5137  
    3636#include <unistd.h>
    3737
    38 #include <libtransmission/bsdtree.h>
    3938#include <libtransmission/bencode.h>
    4039#include <libtransmission/ipcparse.h>
     
    4241#include <libtransmission/version.h>
    4342
     43#include "bsdtree.h"
    4444#include "bsdqueue.h"
    4545#include "client.h"
     
    123123    }
    124124
    125     if( 0 > ipc_addmsg( gl_tree, IPC_MSG_INFO, infomsg ) ||
    126         0 > ipc_addmsg( gl_tree, IPC_MSG_STAT, statmsg ) )
    127     {
    128         return -1;
    129     }
    130 
     125    ipc_addmsg( gl_tree, IPC_MSG_INFO, infomsg );
     126    ipc_addmsg( gl_tree, IPC_MSG_STAT, statmsg );
    131127    ipc_setdefmsg( gl_tree, defmsg );
    132128
  • trunk/daemon/remote.c

    r4909 r5137  
    3737#include <unistd.h>
    3838
    39 #include <libtransmission/bsdtree.h>
    4039#include <libtransmission/ipcparse.h>
    4140#include <libtransmission/transmission.h>
    4241#include <libtransmission/trcompat.h>
    4342
     43#include "bsdtree.h"
    4444#include "bsdqueue.h"
    4545#include "client.h"
  • trunk/daemon/server.c

    r4305 r5137  
    3737#include <unistd.h>
    3838
    39 #include <libtransmission/bsdtree.h>
    4039#include <libtransmission/bencode.h>
    4140#include <libtransmission/ipcparse.h>
    4241
     42#include "bsdtree.h"
    4343#include "errors.h"
    4444#include "misc.h"
     
    101101    }
    102102
    103     if( 0 > ipc_addmsg( gl_tree, IPC_MSG_ADDMANYFILES, addmsg1 ) ||
    104         0 > ipc_addmsg( gl_tree, IPC_MSG_ADDONEFILE,   addmsg2 ) ||
    105         0 > ipc_addmsg( gl_tree, IPC_MSG_AUTOMAP,      intmsg  ) ||
    106         0 > ipc_addmsg( gl_tree, IPC_MSG_AUTOSTART,    intmsg  ) ||
    107         0 > ipc_addmsg( gl_tree, IPC_MSG_CRYPTO,       strmsg  ) ||
    108         0 > ipc_addmsg( gl_tree, IPC_MSG_DOWNLIMIT,    intmsg  ) ||
    109         0 > ipc_addmsg( gl_tree, IPC_MSG_DIR,          strmsg  ) ||
    110         0 > ipc_addmsg( gl_tree, IPC_MSG_GETAUTOMAP,   prefmsg ) ||
    111         0 > ipc_addmsg( gl_tree, IPC_MSG_GETAUTOSTART, prefmsg ) ||
    112         0 > ipc_addmsg( gl_tree, IPC_MSG_GETCRYPTO,    prefmsg ) ||
    113         0 > ipc_addmsg( gl_tree, IPC_MSG_GETDOWNLIMIT, prefmsg ) ||
    114         0 > ipc_addmsg( gl_tree, IPC_MSG_GETDIR,       prefmsg ) ||
    115         0 > ipc_addmsg( gl_tree, IPC_MSG_GETINFO,      infomsg ) ||
    116         0 > ipc_addmsg( gl_tree, IPC_MSG_GETINFOALL,   infomsg ) ||
    117         0 > ipc_addmsg( gl_tree, IPC_MSG_GETPEX,       prefmsg ) ||
    118         0 > ipc_addmsg( gl_tree, IPC_MSG_GETPORT,      prefmsg ) ||
    119         0 > ipc_addmsg( gl_tree, IPC_MSG_GETSTAT,      infomsg ) ||
    120         0 > ipc_addmsg( gl_tree, IPC_MSG_GETSTATALL,   infomsg ) ||
    121         0 > ipc_addmsg( gl_tree, IPC_MSG_GETUPLIMIT,   prefmsg ) ||
    122         0 > ipc_addmsg( gl_tree, IPC_MSG_GETSUP,       supmsg  ) ||
    123         0 > ipc_addmsg( gl_tree, IPC_MSG_LOOKUP,       lookmsg ) ||
    124         0 > ipc_addmsg( gl_tree, IPC_MSG_NOOP,         noopmsg ) ||
    125         0 > ipc_addmsg( gl_tree, IPC_MSG_PEX,          intmsg  ) ||
    126         0 > ipc_addmsg( gl_tree, IPC_MSG_PORT,         intmsg  ) ||
    127         0 > ipc_addmsg( gl_tree, IPC_MSG_QUIT,         quitmsg ) ||
    128         0 > ipc_addmsg( gl_tree, IPC_MSG_REMOVE,       tormsg  ) ||
    129         0 > ipc_addmsg( gl_tree, IPC_MSG_REMOVEALL,    tormsg  ) ||
    130         0 > ipc_addmsg( gl_tree, IPC_MSG_START,        tormsg  ) ||
    131         0 > ipc_addmsg( gl_tree, IPC_MSG_STARTALL,     tormsg  ) ||
    132         0 > ipc_addmsg( gl_tree, IPC_MSG_STOP,         tormsg  ) ||
    133         0 > ipc_addmsg( gl_tree, IPC_MSG_STOPALL,      tormsg  ) ||
    134         0 > ipc_addmsg( gl_tree, IPC_MSG_UPLIMIT,      intmsg  ) )
    135     {
    136         return -1;
    137     }
     103    ipc_addmsg( gl_tree, IPC_MSG_ADDMANYFILES, addmsg1 );
     104    ipc_addmsg( gl_tree, IPC_MSG_ADDONEFILE,   addmsg2 );
     105    ipc_addmsg( gl_tree, IPC_MSG_AUTOMAP,      intmsg  );
     106    ipc_addmsg( gl_tree, IPC_MSG_AUTOSTART,    intmsg  );
     107    ipc_addmsg( gl_tree, IPC_MSG_CRYPTO,       strmsg  );
     108    ipc_addmsg( gl_tree, IPC_MSG_DOWNLIMIT,    intmsg  );
     109    ipc_addmsg( gl_tree, IPC_MSG_DIR,          strmsg  );
     110    ipc_addmsg( gl_tree, IPC_MSG_GETAUTOMAP,   prefmsg );
     111    ipc_addmsg( gl_tree, IPC_MSG_GETAUTOSTART, prefmsg );
     112    ipc_addmsg( gl_tree, IPC_MSG_GETCRYPTO,    prefmsg );
     113    ipc_addmsg( gl_tree, IPC_MSG_GETDOWNLIMIT, prefmsg );
     114    ipc_addmsg( gl_tree, IPC_MSG_GETDIR,       prefmsg );
     115    ipc_addmsg( gl_tree, IPC_MSG_GETINFO,      infomsg );
     116    ipc_addmsg( gl_tree, IPC_MSG_GETINFOALL,   infomsg );
     117    ipc_addmsg( gl_tree, IPC_MSG_GETPEX,       prefmsg );
     118    ipc_addmsg( gl_tree, IPC_MSG_GETPORT,      prefmsg );
     119    ipc_addmsg( gl_tree, IPC_MSG_GETSTAT,      infomsg );
     120    ipc_addmsg( gl_tree, IPC_MSG_GETSTATALL,   infomsg );
     121    ipc_addmsg( gl_tree, IPC_MSG_GETUPLIMIT,   prefmsg );
     122    ipc_addmsg( gl_tree, IPC_MSG_GETSUP,       supmsg  );
     123    ipc_addmsg( gl_tree, IPC_MSG_LOOKUP,       lookmsg );
     124    ipc_addmsg( gl_tree, IPC_MSG_NOOP,         noopmsg );
     125    ipc_addmsg( gl_tree, IPC_MSG_PEX,          intmsg  );
     126    ipc_addmsg( gl_tree, IPC_MSG_PORT,         intmsg  );
     127    ipc_addmsg( gl_tree, IPC_MSG_QUIT,         quitmsg );
     128    ipc_addmsg( gl_tree, IPC_MSG_REMOVE,       tormsg  );
     129    ipc_addmsg( gl_tree, IPC_MSG_REMOVEALL,    tormsg  );
     130    ipc_addmsg( gl_tree, IPC_MSG_START,        tormsg  );
     131    ipc_addmsg( gl_tree, IPC_MSG_STARTALL,     tormsg  );
     132    ipc_addmsg( gl_tree, IPC_MSG_STOP,         tormsg  );
     133    ipc_addmsg( gl_tree, IPC_MSG_STOPALL,      tormsg  );
     134    ipc_addmsg( gl_tree, IPC_MSG_UPLIMIT,      intmsg  );
    138135
    139136    ipc_setdefmsg( gl_tree, defmsg );
  • trunk/daemon/torrents.c

    r4988 r5137  
    4040#include <unistd.h>
    4141
    42 #include <libtransmission/bsdtree.h>
    4342#include <libtransmission/bencode.h>
    4443#include <libtransmission/transmission.h>
    4544#include <libtransmission/trcompat.h>
    4645
     46#include "bsdtree.h"
    4747#include "errors.h"
    4848#include "misc.h"
  • trunk/gtk/ipc.c

    r5127 r5137  
    538538    tr_ctor              * ctor;
    539539
    540     if( NULL == val || TYPE_DICT != val->type )
     540    if( !val || ( val->type != TYPE_DICT ) )
    541541    {
    542542        simpleresp( con, tag, IPC_MSG_BAD );
     
    11441144
    11451145  con->msgs = ipc_initmsgs();
    1146   if( NULL == con->msgs ||
    1147       0 > ipc_addmsg( con->msgs, IPC_MSG_ADDMANYFILES, smsg_add ) ||
    1148       0 > ipc_addmsg( con->msgs, IPC_MSG_ADDONEFILE,   smsg_addone ) ||
    1149       0 > ipc_addmsg( con->msgs, IPC_MSG_AUTOMAP,      smsg_int ) ||
    1150       0 > ipc_addmsg( con->msgs, IPC_MSG_AUTOSTART,    smsg_int ) ||
    1151       0 > ipc_addmsg( con->msgs, IPC_MSG_DIR,          smsg_str ) ||
    1152       0 > ipc_addmsg( con->msgs, IPC_MSG_DOWNLIMIT,    smsg_int ) ||
    1153       0 > ipc_addmsg( con->msgs, IPC_MSG_GETAUTOMAP,   smsg_pref ) ||
    1154       0 > ipc_addmsg( con->msgs, IPC_MSG_GETAUTOSTART, smsg_pref ) ||
    1155       0 > ipc_addmsg( con->msgs, IPC_MSG_GETDIR,       smsg_pref ) ||
    1156       0 > ipc_addmsg( con->msgs, IPC_MSG_GETDOWNLIMIT, smsg_pref ) ||
    1157       0 > ipc_addmsg( con->msgs, IPC_MSG_GETINFO,      smsg_info ) ||
    1158       0 > ipc_addmsg( con->msgs, IPC_MSG_GETINFOALL,   smsg_infoall ) ||
    1159       0 > ipc_addmsg( con->msgs, IPC_MSG_GETPEX,       smsg_pref ) ||
    1160       0 > ipc_addmsg( con->msgs, IPC_MSG_GETPORT,      smsg_pref ) ||
    1161       0 > ipc_addmsg( con->msgs, IPC_MSG_GETSTAT,      smsg_info ) ||
    1162       0 > ipc_addmsg( con->msgs, IPC_MSG_GETSTATALL,   smsg_infoall ) ||
    1163       0 > ipc_addmsg( con->msgs, IPC_MSG_GETUPLIMIT,   smsg_pref ) ||
    1164       0 > ipc_addmsg( con->msgs, IPC_MSG_LOOKUP,       smsg_look ) ||
    1165       0 > ipc_addmsg( con->msgs, IPC_MSG_NOOP,         smsg_noop ) ||
    1166       0 > ipc_addmsg( con->msgs, IPC_MSG_PEX,          smsg_int ) ||
    1167       0 > ipc_addmsg( con->msgs, IPC_MSG_PORT,         smsg_int ) ||
    1168       0 > ipc_addmsg( con->msgs, IPC_MSG_QUIT,         smsg_quit ) ||
    1169       0 > ipc_addmsg( con->msgs, IPC_MSG_REMOVE,       smsg_tor ) ||
    1170       0 > ipc_addmsg( con->msgs, IPC_MSG_REMOVEALL,    smsg_torall ) ||
    1171       0 > ipc_addmsg( con->msgs, IPC_MSG_START,        smsg_tor ) ||
    1172       0 > ipc_addmsg( con->msgs, IPC_MSG_STARTALL,     smsg_torall ) ||
    1173       0 > ipc_addmsg( con->msgs, IPC_MSG_STOP,         smsg_tor ) ||
    1174       0 > ipc_addmsg( con->msgs, IPC_MSG_STOPALL,      smsg_torall ) ||
    1175       0 > ipc_addmsg( con->msgs, IPC_MSG_SUP,          smsg_sup ) ||
    1176       0 > ipc_addmsg( con->msgs, IPC_MSG_UPLIMIT,      smsg_int ) )
     1146  if( NULL == con->msgs )
    11771147  {
    11781148      errmsg( con->u.serv.wind, _("Failed to set up IPC: %s"),
     
    11821152  }
    11831153
     1154  ipc_addmsg( con->msgs, IPC_MSG_ADDMANYFILES, smsg_add );
     1155  ipc_addmsg( con->msgs, IPC_MSG_ADDONEFILE,   smsg_addone );
     1156  ipc_addmsg( con->msgs, IPC_MSG_AUTOMAP,      smsg_int );
     1157  ipc_addmsg( con->msgs, IPC_MSG_AUTOSTART,    smsg_int );
     1158  ipc_addmsg( con->msgs, IPC_MSG_DIR,          smsg_str );
     1159  ipc_addmsg( con->msgs, IPC_MSG_DOWNLIMIT,    smsg_int );
     1160  ipc_addmsg( con->msgs, IPC_MSG_GETAUTOMAP,   smsg_pref );
     1161  ipc_addmsg( con->msgs, IPC_MSG_GETAUTOSTART, smsg_pref );
     1162  ipc_addmsg( con->msgs, IPC_MSG_GETDIR,       smsg_pref );
     1163  ipc_addmsg( con->msgs, IPC_MSG_GETDOWNLIMIT, smsg_pref );
     1164  ipc_addmsg( con->msgs, IPC_MSG_GETINFO,      smsg_info );
     1165  ipc_addmsg( con->msgs, IPC_MSG_GETINFOALL,   smsg_infoall );
     1166  ipc_addmsg( con->msgs, IPC_MSG_GETPEX,       smsg_pref );
     1167  ipc_addmsg( con->msgs, IPC_MSG_GETPORT,      smsg_pref );
     1168  ipc_addmsg( con->msgs, IPC_MSG_GETSTAT,      smsg_info );
     1169  ipc_addmsg( con->msgs, IPC_MSG_GETSTATALL,   smsg_infoall );
     1170  ipc_addmsg( con->msgs, IPC_MSG_GETUPLIMIT,   smsg_pref );
     1171  ipc_addmsg( con->msgs, IPC_MSG_LOOKUP,       smsg_look );
     1172  ipc_addmsg( con->msgs, IPC_MSG_NOOP,         smsg_noop );
     1173  ipc_addmsg( con->msgs, IPC_MSG_PEX,          smsg_int );
     1174  ipc_addmsg( con->msgs, IPC_MSG_PORT,         smsg_int );
     1175  ipc_addmsg( con->msgs, IPC_MSG_QUIT,         smsg_quit );
     1176  ipc_addmsg( con->msgs, IPC_MSG_REMOVE,       smsg_tor );
     1177  ipc_addmsg( con->msgs, IPC_MSG_REMOVEALL,    smsg_torall );
     1178  ipc_addmsg( con->msgs, IPC_MSG_START,        smsg_tor );
     1179  ipc_addmsg( con->msgs, IPC_MSG_STARTALL,     smsg_torall );
     1180  ipc_addmsg( con->msgs, IPC_MSG_STOP,         smsg_tor );
     1181  ipc_addmsg( con->msgs, IPC_MSG_STOPALL,      smsg_torall );
     1182  ipc_addmsg( con->msgs, IPC_MSG_SUP,          smsg_sup );
     1183  ipc_addmsg( con->msgs, IPC_MSG_UPLIMIT,      smsg_int );
     1184
    11841185  ipc_setdefmsg( con->msgs, all_default );
    11851186
  • trunk/libtransmission/Makefile.am

    r5042 r5137  
    3939noinst_HEADERS = \
    4040    bencode.h \
    41     bsdtree.h \
    4241    clients.h \
    4342    crypto.h \
  • trunk/libtransmission/ipcparse.c

    r5127 r5137  
    3535
    3636#include "ipcparse.h"
    37 #include "bsdtree.h"
    38 
    39 /* begin copy-paste from daemon/misc.h */
    40 
    41 #define ARRAYLEN( ary )         ( sizeof( ary ) / sizeof( (ary)[0] ) )
    42 
    43 #ifndef MIN
    44 #define MIN( aa, bb )           ( (aa) < (bb) ? (aa) : (bb) )
    45 #endif
    46 #ifndef MAX
    47 #define MAX( aa, bb )           ( (aa) > (bb) ? (aa) : (bb) )
    48 #endif
    49 
    50 #undef NULL
    51 #define NULL                    ( ( void * )0 )
    52 
    53 #define SAFEFREE( ptr )                                                       \
    54     do                                                                        \
    55     {                                                                         \
    56         int saved = errno;                                                    \
    57         free( ptr );                                                          \
    58         errno = saved;                                                        \
    59     }                                                                         \
     37
     38#define TR_N_ELEMENTS( ary ) ( sizeof( ary ) / sizeof( (ary)[0] ) )
     39
     40#define SAFEFREE( ptr )      \
     41    do                       \
     42    {                        \
     43        int saved = errno;   \
     44        free( ptr );         \
     45        errno = saved;       \
     46    }                        \
    6047    while( 0 )
    61 #define SAFEFREESTRLIST( ptr )                                                \
    62     do                                                                        \
    63     {                                                                         \
    64         int saved = errno;                                                    \
    65         FREESTRLIST( ptr );                                                   \
    66         errno = saved;                                                        \
    67     }                                                                         \
     48
     49#define SAFEBENCFREE( val )  \
     50    do                       \
     51    {                        \
     52        int saved = errno;   \
     53        tr_bencFree( val );  \
     54        errno = saved;       \
     55    }                        \
    6856    while( 0 )
    69 #define SAFEBENCFREE( val )                                                   \
    70     do                                                                        \
    71     {                                                                         \
    72         int saved = errno;                                                    \
    73         tr_bencFree( val );                                                   \
    74         errno = saved;                                                        \
    75     }                                                                         \
    76     while( 0 )
    77 
    78 #define INTCMP_FUNC( name, type, id )                                         \
    79 int                                                                           \
    80 name( struct type * _icf_first, struct type * _icf_second )                   \
    81 {                                                                             \
    82     if( _icf_first->id < _icf_second->id )                                    \
    83     {                                                                         \
    84         return -1;                                                            \
    85     }                                                                         \
    86     else if( _icf_first->id > _icf_second->id )                               \
    87     {                                                                         \
    88         return 1;                                                             \
    89     }                                                                         \
    90     else                                                                      \
    91     {                                                                         \
    92         return 0;                                                             \
    93     }                                                                         \
    94 }
    95 
    96 /* end copy-paste from daemon/misc.h */
    9757
    9858/* IPC protocol version */
     
    10767{
    10868    const char        * name;
    109     const int          minvers;
    110     const enum ipc_msg id;
    111     RB_ENTRY( msg )    link;
     69    const int           minvers;
     70    const enum ipc_msg  id;
    11271};
    11372
     
    11675    const char    * name;
    11776    const int       type;
    118     RB_ENTRY( inf ) link;
    11977};
    12078
     
    12381    int             id;
    12482    trd_msgfunc     func;
    125     RB_ENTRY( msgfunc ) link;
    12683};
    12784
    128 RB_HEAD( msgtree, msg );
    129 RB_HEAD( inftree, inf );
    130 RB_HEAD( functree, msgfunc );
    131 
    13285struct ipc_funcs
    13386{
    134     struct functree msgs;
    135     trd_msgfunc    def;
     87    trd_msgfunc msgs[IPC__MSG_COUNT];
     88    trd_msgfunc def;
    13689};
    13790
    138 static struct msg gl_msgs[] =
    139 {
    140     { "addfiles",            1, IPC_MSG_ADDMANYFILES, RB_ENTRY_INITIALIZER() },
    141     { "addfile-detailed",    2, IPC_MSG_ADDONEFILE,   RB_ENTRY_INITIALIZER() },
    142     { "automap",             2, IPC_MSG_AUTOMAP,      RB_ENTRY_INITIALIZER() },
    143     { "autostart",           2, IPC_MSG_AUTOSTART,    RB_ENTRY_INITIALIZER() },
    144     { "bad-format",          2, IPC_MSG_BAD,          RB_ENTRY_INITIALIZER() },
    145     { "encryption",          2, IPC_MSG_CRYPTO,       RB_ENTRY_INITIALIZER() },
    146     { "directory",           2, IPC_MSG_DIR,          RB_ENTRY_INITIALIZER() },
    147     { "downlimit",           2, IPC_MSG_DOWNLIMIT,    RB_ENTRY_INITIALIZER() },
    148     { "failed",              2, IPC_MSG_FAIL,         RB_ENTRY_INITIALIZER() },
    149     { "get-automap",         2, IPC_MSG_GETAUTOMAP,   RB_ENTRY_INITIALIZER() },
    150     { "get-autostart",       2, IPC_MSG_GETAUTOSTART, RB_ENTRY_INITIALIZER() },
    151     { "get-encryption",      2, IPC_MSG_GETCRYPTO,    RB_ENTRY_INITIALIZER() },
    152     { "get-directory",       2, IPC_MSG_GETDIR,       RB_ENTRY_INITIALIZER() },
    153     { "get-downlimit",       2, IPC_MSG_GETDOWNLIMIT, RB_ENTRY_INITIALIZER() },
    154     { "get-info",            2, IPC_MSG_GETINFO,      RB_ENTRY_INITIALIZER() },
    155     { "get-info-all",        2, IPC_MSG_GETINFOALL,   RB_ENTRY_INITIALIZER() },
    156     { "get-pex",             2, IPC_MSG_GETPEX,       RB_ENTRY_INITIALIZER() },
    157     { "get-port",            2, IPC_MSG_GETPORT,      RB_ENTRY_INITIALIZER() },
    158     { "get-status",          2, IPC_MSG_GETSTAT,      RB_ENTRY_INITIALIZER() },
    159     { "get-status-all",      2, IPC_MSG_GETSTATALL,   RB_ENTRY_INITIALIZER() },
    160     { "get-supported",       2, IPC_MSG_GETSUP,       RB_ENTRY_INITIALIZER() },
    161     { "get-uplimit",         2, IPC_MSG_GETUPLIMIT,   RB_ENTRY_INITIALIZER() },
    162     { "lookup",              2, IPC_MSG_LOOKUP,       RB_ENTRY_INITIALIZER() },
    163     { "info",                2, IPC_MSG_INFO,         RB_ENTRY_INITIALIZER() },
    164     { "noop",                2, IPC_MSG_NOOP,         RB_ENTRY_INITIALIZER() },
    165     { "not-supported",       2, IPC_MSG_NOTSUP,       RB_ENTRY_INITIALIZER() },
    166     { "pex",                 2, IPC_MSG_PEX,          RB_ENTRY_INITIALIZER() },
    167     { "port",                2, IPC_MSG_PORT,         RB_ENTRY_INITIALIZER() },
    168     { "quit",                1, IPC_MSG_QUIT,         RB_ENTRY_INITIALIZER() },
    169     { "remove",              2, IPC_MSG_REMOVE,       RB_ENTRY_INITIALIZER() },
    170     { "remove-all",          2, IPC_MSG_REMOVEALL,    RB_ENTRY_INITIALIZER() },
    171     { "start",               2, IPC_MSG_START,        RB_ENTRY_INITIALIZER() },
    172     { "start-all",           2, IPC_MSG_STARTALL,     RB_ENTRY_INITIALIZER() },
    173     { "status",              2, IPC_MSG_STAT,         RB_ENTRY_INITIALIZER() },
    174     { "stop",                2, IPC_MSG_STOP,         RB_ENTRY_INITIALIZER() },
    175     { "stop-all",            2, IPC_MSG_STOPALL,      RB_ENTRY_INITIALIZER() },
    176     { "succeeded",           2, IPC_MSG_OK,           RB_ENTRY_INITIALIZER() },
    177     { "supported",           2, IPC_MSG_SUP,          RB_ENTRY_INITIALIZER() },
    178     { "uplimit",             2, IPC_MSG_UPLIMIT,      RB_ENTRY_INITIALIZER() },
    179     { "version",             1, IPC_MSG_VERSION,      RB_ENTRY_INITIALIZER() },
     91/* these names must be sorted for strcmp() */
     92static const struct msg gl_msgs[] =
     93{
     94    { "addfile-detailed",    2, IPC_MSG_ADDONEFILE    },
     95    { "addfiles",            1, IPC_MSG_ADDMANYFILES  },
     96    { "automap",             2, IPC_MSG_AUTOMAP       },
     97    { "autostart",           2, IPC_MSG_AUTOSTART     },
     98    { "bad-format",          2, IPC_MSG_BAD           },
     99    { "directory",           2, IPC_MSG_DIR           },
     100    { "downlimit",           2, IPC_MSG_DOWNLIMIT     },
     101    { "encryption",          2, IPC_MSG_CRYPTO        },
     102    { "failed",              2, IPC_MSG_FAIL          },
     103    { "get-automap",         2, IPC_MSG_GETAUTOMAP    },
     104    { "get-autostart",       2, IPC_MSG_GETAUTOSTART  },
     105    { "get-directory",       2, IPC_MSG_GETDIR        },
     106    { "get-downlimit",       2, IPC_MSG_GETDOWNLIMIT  },
     107    { "get-encryption",      2, IPC_MSG_GETCRYPTO     },
     108    { "get-info",            2, IPC_MSG_GETINFO       },
     109    { "get-info-all",        2, IPC_MSG_GETINFOALL    },
     110    { "get-pex",             2, IPC_MSG_GETPEX        },
     111    { "get-port",            2, IPC_MSG_GETPORT       },
     112    { "get-status",          2, IPC_MSG_GETSTAT       },
     113    { "get-status-all",      2, IPC_MSG_GETSTATALL    },
     114    { "get-supported",       2, IPC_MSG_GETSUP        },
     115    { "get-uplimit",         2, IPC_MSG_GETUPLIMIT    },
     116    { "info",                2, IPC_MSG_INFO          },
     117    { "lookup",              2, IPC_MSG_LOOKUP        },
     118    { "noop",                2, IPC_MSG_NOOP          },
     119    { "not-supported",       2, IPC_MSG_NOTSUP        },
     120    { "pex",                 2, IPC_MSG_PEX           },
     121    { "port",                2, IPC_MSG_PORT          },
     122    { "quit",                1, IPC_MSG_QUIT          },
     123    { "remove",              2, IPC_MSG_REMOVE        },
     124    { "remove-all",          2, IPC_MSG_REMOVEALL     },
     125    { "start",               2, IPC_MSG_START         },
     126    { "start-all",           2, IPC_MSG_STARTALL      },
     127    { "status",              2, IPC_MSG_STAT          },
     128    { "stop",                2, IPC_MSG_STOP          },
     129    { "stop-all",            2, IPC_MSG_STOPALL       },
     130    { "succeeded",           2, IPC_MSG_OK            },
     131    { "supported",           2, IPC_MSG_SUP           },
     132    { "uplimit",             2, IPC_MSG_UPLIMIT       },
     133    { "version",             1, IPC_MSG_VERSION       }
    180134};
    181135
    182 static struct inf gl_inf[] =
    183 {
    184     { "comment",                IPC_INF_COMMENT,      RB_ENTRY_INITIALIZER() },
    185     { "creator",                IPC_INF_CREATOR,      RB_ENTRY_INITIALIZER() },
    186     { "date",                   IPC_INF_DATE,         RB_ENTRY_INITIALIZER() },
    187     { "files",                  IPC_INF_FILES,        RB_ENTRY_INITIALIZER() },
    188     { "hash",                   IPC_INF_HASH,         RB_ENTRY_INITIALIZER() },
    189     { "id",                     IPC_INF_ID,           RB_ENTRY_INITIALIZER() },
    190     { "name",                   IPC_INF_NAME,         RB_ENTRY_INITIALIZER() },
    191     { "path",                   IPC_INF_PATH,         RB_ENTRY_INITIALIZER() },
    192     { "private",                IPC_INF_PRIVATE,      RB_ENTRY_INITIALIZER() },
    193     { "size",                   IPC_INF_SIZE,         RB_ENTRY_INITIALIZER() },
    194     { "trackers",               IPC_INF_TRACKERS,     RB_ENTRY_INITIALIZER() },
     136/* these names must be sorted for strcmp() */
     137static const struct inf gl_inf[] =
     138{
     139    { "comment",                IPC_INF_COMMENT   },
     140    { "creator",                IPC_INF_CREATOR   },
     141    { "date",                   IPC_INF_DATE      },
     142    { "files",                  IPC_INF_FILES     },
     143    { "hash",                   IPC_INF_HASH      },
     144    { "id",                     IPC_INF_ID        },
     145    { "name",                   IPC_INF_NAME      },
     146    { "path",                   IPC_INF_PATH      },
     147    { "private",                IPC_INF_PRIVATE   },
     148    { "size",                   IPC_INF_SIZE      },
     149    { "trackers",               IPC_INF_TRACKERS  }
    195150};
    196151
    197 static struct inf gl_stat[] =
    198 {
    199     { "completed",              IPC_ST_COMPLETED,     RB_ENTRY_INITIALIZER() },
    200     { "download-speed",         IPC_ST_DOWNSPEED,     RB_ENTRY_INITIALIZER() },
    201     { "download-total",         IPC_ST_DOWNTOTAL,     RB_ENTRY_INITIALIZER() },
    202     { "download-valid",         IPC_ST_DOWNVALID,     RB_ENTRY_INITIALIZER() },
    203     { "error",                  IPC_ST_ERROR,         RB_ENTRY_INITIALIZER() },
    204     { "error-message",          IPC_ST_ERRMSG,        RB_ENTRY_INITIALIZER() },
    205     { "eta",                    IPC_ST_ETA,           RB_ENTRY_INITIALIZER() },
    206     { "id",                     IPC_ST_ID,            RB_ENTRY_INITIALIZER() },
    207     { "peers-downloading",      IPC_ST_PEERDOWN,      RB_ENTRY_INITIALIZER() },
    208     { "peers-from",             IPC_ST_PEERFROM,      RB_ENTRY_INITIALIZER() },
    209     { "peers-total",            IPC_ST_PEERTOTAL,     RB_ENTRY_INITIALIZER() },
    210     { "peers-uploading",        IPC_ST_PEERUP,        RB_ENTRY_INITIALIZER() },
    211     { "running",                IPC_ST_RUNNING,       RB_ENTRY_INITIALIZER() },
    212     { "state",                  IPC_ST_STATE,         RB_ENTRY_INITIALIZER() },
    213     { "swarm-speed",            IPC_ST_SWARM,         RB_ENTRY_INITIALIZER() },
    214     { "tracker",                IPC_ST_TRACKER,       RB_ENTRY_INITIALIZER() },
    215     { "scrape-completed",       IPC_ST_TKDONE,        RB_ENTRY_INITIALIZER() },
    216     { "scrape-leechers",        IPC_ST_TKLEECH,       RB_ENTRY_INITIALIZER() },
    217     { "scrape-seeders",         IPC_ST_TKSEED,        RB_ENTRY_INITIALIZER() },
    218     { "upload-speed",           IPC_ST_UPSPEED,       RB_ENTRY_INITIALIZER() },
    219     { "upload-total",           IPC_ST_UPTOTAL,       RB_ENTRY_INITIALIZER() },
     152/* these names must be sorted for strcmp() */
     153static const struct inf gl_stat[] =
     154{
     155    { "completed",              IPC_ST_COMPLETED },
     156    { "download-speed",         IPC_ST_DOWNSPEED },
     157    { "download-total",         IPC_ST_DOWNTOTAL },
     158    { "download-valid",         IPC_ST_DOWNVALID },
     159    { "error",                  IPC_ST_ERROR     },
     160    { "error-message",          IPC_ST_ERRMSG    },
     161    { "eta",                    IPC_ST_ETA       },
     162    { "id",                     IPC_ST_ID        },
     163    { "peers-downloading",      IPC_ST_PEERDOWN  },
     164    { "peers-from",             IPC_ST_PEERFROM  },
     165    { "peers-total",            IPC_ST_PEERTOTAL },
     166    { "peers-uploading",        IPC_ST_PEERUP    },
     167    { "running",                IPC_ST_RUNNING   },
     168    { "scrape-completed",       IPC_ST_TKDONE    },
     169    { "scrape-leechers",        IPC_ST_TKLEECH   },
     170    { "scrape-seeders",         IPC_ST_TKSEED    },
     171    { "state",                  IPC_ST_STATE     },
     172    { "swarm-speed",            IPC_ST_SWARM     },
     173    { "tracker",                IPC_ST_TRACKER   },
     174    { "upload-speed",           IPC_ST_UPSPEED   },
     175    { "upload-total",           IPC_ST_UPTOTAL   }
    220176};
    221 
    222 static int          handlevers ( struct ipc_info *, tr_benc * );
    223 static int          handlemsgs ( struct ipc_info *, tr_benc *, void * );
    224 static int          gotmsg     ( struct ipc_info *, tr_benc *, tr_benc *,
    225                                  tr_benc *, void * );
    226 static int          msgcmp     ( struct msg *, struct msg * );
    227 static int          infcmp     ( struct inf *, struct inf * );
    228 static struct msg * msglookup  ( const char * );
    229 static int          filltracker( tr_benc *, const tr_tracker_info * );
    230 static int          handlercmp ( struct msgfunc *, struct msgfunc * );
    231 
    232 RB_GENERATE_STATIC( msgtree, msg, link, msgcmp )
    233 RB_GENERATE_STATIC( inftree, inf, link, infcmp )
    234 RB_GENERATE_STATIC( functree, msgfunc, link, handlercmp )
    235 INTCMP_FUNC( handlercmp, msgfunc, id )
    236177
    237178struct ipc_funcs *
    238179ipc_initmsgs( void )
    239180{
    240     struct ipc_funcs * tree;
    241 
    242     tree = malloc( sizeof *tree );
    243     if( NULL != tree )
    244     {
    245         RB_INIT( &tree->msgs );
    246         tree->def = (trd_msgfunc) NULL;
    247     }
    248 
    249     return tree;
    250 }
    251 
    252 int
     181    return tr_new0( struct ipc_funcs, 1 );
     182}
     183
     184void
    253185ipc_addmsg( struct ipc_funcs * tree, enum ipc_msg id, trd_msgfunc func )
    254186{
    255     struct msgfunc key, * entry;
    256 
    257187    assert( MSGVALID( id ) );
    258188    assert( IPC_MSG_VERSION != id );
    259189
    260     memset( &key, 0, sizeof key );
    261     key.id = id;
    262     entry = RB_FIND( functree, &tree->msgs, &key );
    263     assert( NULL == entry );
    264 
    265     entry = calloc( 1, sizeof *entry );
    266     if( NULL == entry )
    267     {
    268         return -1;
    269     }
    270 
    271     entry->id   = id;
    272     entry->func = func;
    273     entry = RB_INSERT( functree, &tree->msgs, entry );
    274     assert( NULL == entry );
    275 
    276     return 0;
     190    tree->msgs[id] = func;
    277191}
    278192
     
    286200ipc_freemsgs( struct ipc_funcs * tree )
    287201{
    288     struct msgfunc * ii, * next;
    289 
    290     for( ii = RB_MIN( functree, &tree->msgs ); NULL != ii; ii = next )
    291     {
    292         next = RB_NEXT( functree, &tree->msgs, ii );
    293         RB_REMOVE( functree, &tree->msgs, ii );
    294         free( ii );
    295     }
    296     free( tree );
     202    tr_free( tree );
    297203}
    298204
     
    302208    struct ipc_info * info;
    303209
    304     info = calloc( 1, sizeof *info );
    305     if( NULL != info )
     210    if(( info = calloc( 1, sizeof *info )))
    306211    {
    307212        info->funcs = funcs;
     
    315220ipc_freecon( struct ipc_info * info )
    316221{
    317     if( NULL != info )
     222    if( info )
    318223    {
    319224        free( info->label );
     
    366271
    367272uint8_t *
    368 ipc_mkval( tr_benc * pk, size_t * setmeSize )
     273ipc_mkval( const tr_benc * pk, size_t * setmeSize )
    369274{
    370275    int bencSize = 0;
     
    394299
    395300    if( NULL == ipc_initval( info, id, tag, &pk, TYPE_STR ) )
    396     {
    397301        return NULL;
    398     }
    399302
    400303    ret = ipc_mkval( &pk, len );
     
    412315
    413316    val = ipc_initval( info, id, tag, &pk, TYPE_INT );
    414     if( NULL == val )
    415     {
     317    if( !val )
    416318        return NULL;
    417     }
    418319
    419320    val->val.i = num;
     
    432333
    433334    val = ipc_initval( info, id, tag, &pk, TYPE_STR );
    434     if( NULL == val )
    435     {
     335    if( !val )
    436336        return NULL;
    437     }
    438337
    439338    tr_bencInitStr( val, str, -1, 1 );
     
    480379    tr_benc   pk, * top, * idlist, * typelist;
    481380    size_t       ii, typecount, used;
    482     struct inf * typearray;
     381    const struct inf * typearray;
    483382    uint8_t    * ret;
    484383
     
    528427        case IPC_MSG_GETINFO:
    529428        case IPC_MSG_GETINFOALL:
    530             typecount = ARRAYLEN( gl_inf );
     429            typecount = TR_N_ELEMENTS( gl_inf );
    531430            typearray = gl_inf;
    532431            break;
    533432        case IPC_MSG_GETSTAT:
    534433        case IPC_MSG_GETSTATALL:
    535             typecount = ARRAYLEN( gl_stat );
     434            typecount = TR_N_ELEMENTS( gl_stat );
    536435            typearray = gl_stat;
    537436            break;
     
    572471}
    573472
     473static int
     474filltracker( tr_benc * val, const tr_tracker_info * tk )
     475{
     476    tr_bencInit( val, TYPE_DICT );
     477    if( tr_bencDictReserve( val, ( NULL == tk->scrape ? 3 : 4 ) ) )
     478        return -1;
     479
     480    tr_bencInitStr( tr_bencDictAdd( val, "address" ),  tk->address,  -1, 1 );
     481    tr_bencInitInt( tr_bencDictAdd( val, "port" ),     tk->port );
     482    tr_bencInitStr( tr_bencDictAdd( val, "announce" ), tk->announce, -1, 1 );
     483    if( NULL != tk->scrape )
     484        tr_bencInitStr( tr_bencDictAdd( val, "scrape" ), tk->scrape, -1, 1 );
     485
     486    return 0;
     487}
     488
    574489int
    575490ipc_addinfo( tr_benc * list, int tor, const tr_info * inf, int types )
     
    594509            continue;
    595510        }
    596         assert( ARRAYLEN( gl_inf ) > ( unsigned )ii );
     511        assert( TR_N_ELEMENTS( gl_inf ) > ( unsigned )ii );
    597512        assert( gl_inf[ii].type == ( 1 << ii ) );
    598513        /* check for missing optional info */
    599         if( ( IPC_INF_COMMENT == ( 1 << ii ) && '\0' == inf->comment ) ||
    600             ( IPC_INF_CREATOR == ( 1 << ii ) && '\0' == inf->creator ) ||
     514        if( ( IPC_INF_COMMENT == ( 1 << ii ) && !*inf->comment ) ||
     515            ( IPC_INF_CREATOR == ( 1 << ii ) && !*inf->creator ) ||
    601516            ( IPC_INF_DATE    == ( 1 << ii ) &&   0  >= inf->dateCreated ) )
    602517        {
     
    617532        }
    618533        /* check for missing optional info */
    619         if( ( IPC_INF_COMMENT == ( 1 << ii ) && '\0' == inf->comment ) ||
    620             ( IPC_INF_CREATOR == ( 1 << ii ) && '\0' == inf->creator ) ||
     534        if( ( IPC_INF_COMMENT == ( 1 << ii ) && !*inf->comment ) ||
     535            ( IPC_INF_CREATOR == ( 1 << ii ) && !*inf->creator ) ||
    621536            ( IPC_INF_DATE    == ( 1 << ii ) && 0 >= inf->dateCreated ) )
    622537        {
     
    720635
    721636    if( tr_bencListReserve( list, 1 ) )
    722     {
    723637        return -1;
    724     }
     638
    725639    dict = tr_bencListAdd( list );
    726640
    727641    for( ii = used = 0; IPC_ST__MAX > 1 << ii; ii++ )
    728     {
    729642        if( types & ( 1 << ii ) )
    730         {
    731643            used++;
    732         }
    733     }
     644
    734645    tr_bencInit( dict, TYPE_DICT );
    735646    if( tr_bencDictReserve( dict, used ) )
    736     {
    737647        return -1;
    738     }
    739648
    740649    for( ii = 0; IPC_ST__MAX > 1 << ii; ii++ )
    741650    {
    742651        if( !( types & ( 1 << ii ) ) )
    743         {
    744652            continue;
    745         }
    746         assert( ARRAYLEN( gl_stat ) > ( unsigned )ii );
     653
     654        assert( TR_N_ELEMENTS( gl_stat ) > ( unsigned )ii );
    747655        assert( gl_stat[ii].type == ( 1 << ii ) );
    748656        item = tr_bencDictAdd( dict, gl_stat[ii].name );
     
    912820}
    913821
    914 ssize_t
    915 ipc_parse( struct ipc_info * info, uint8_t * buf, ssize_t total, void * arg )
    916 {
    917     char        hex[IPC_MIN_MSG_LEN+1], * end;
    918     ssize_t     off, len;
    919     tr_benc  benc;
    920 
    921     for( off = 0; off + IPC_MIN_MSG_LEN < total; off += IPC_MIN_MSG_LEN + len )
    922     {
    923         memcpy( hex, buf + off, IPC_MIN_MSG_LEN );
    924         hex[IPC_MIN_MSG_LEN] = '\0';
    925         end = NULL;
    926         len = strtol( hex, &end, 16 );
    927         if( hex + IPC_MIN_MSG_LEN != end ||
    928             0 > len || IPC_MAX_MSG_LEN < len )
    929         {
    930             errno = EINVAL;
    931             return -1;
    932         }
    933         if( off + IPC_MIN_MSG_LEN + len > total )
    934         {
    935             break;
    936         }
    937         errno = 0;
    938         if( tr_bencLoad( buf + off + IPC_MIN_MSG_LEN, len, &benc, NULL ) )
    939         {
    940             if( 0 == errno )
    941             {
    942                 errno = EINVAL;
    943             }
    944             return -1;
    945         }
    946         if( 0 > ( HASVERS( info ) ? handlemsgs( info, &benc, arg ) :
    947                                     handlevers( info, &benc ) ) )
    948         {
    949             SAFEBENCFREE( &benc );
    950             return -1;
    951         }
    952         tr_bencFree( &benc );
    953     }
    954 
    955     return off;
    956 }
    957 
    958822static int
    959823handlevers( struct ipc_info * info, tr_benc * dict )
     
    1012876
    1013877    info->vers = MIN( PROTO_VERS_MAX, max );
     878
     879    return 0;
     880}
     881
     882static int
     883compareNameToMsg( const void * a, const void * b )
     884{
     885    const struct msg * msg = b;
     886    return strcmp( a, msg->name );
     887}
     888
     889static const struct msg *
     890msglookup( const char * name )
     891{
     892    return bsearch( name,
     893                    gl_msgs, TR_N_ELEMENTS( gl_msgs ), sizeof( struct msg ),
     894                    compareNameToMsg );
     895}
     896
     897static int
     898gotmsg( struct ipc_info * info, tr_benc * name, tr_benc * val,
     899        tr_benc * tagval, void * arg )
     900{
     901    const struct msg * msg;
     902    int64_t            tag;
     903
     904    if( TYPE_STR != name->type )
     905    {
     906        errno = EINVAL;
     907        return -1;
     908    }
     909
     910    if( NULL == tagval )
     911    {
     912        tag = -1;
     913    }
     914    else
     915    {
     916        if( TYPE_INT != tagval->type )
     917        {
     918            errno = EINVAL;
     919            return -1;
     920        }
     921        tag = tagval->val.i;
     922    }
     923
     924    msg = msglookup( name->val.s.s );
     925    if( msg && msg->minvers <= info->vers )
     926    {
     927        if( info->funcs->msgs[msg->id] != NULL )
     928        {
     929            (*info->funcs->msgs[msg->id])( msg->id, val, tag, arg );
     930        }
     931        else if( info->funcs->def )
     932        {
     933            info->funcs->def( msg->id, val, tag, arg );
     934        }
     935    }
     936    else if( NULL != info->funcs->def )
     937        info->funcs->def( IPC__MSG_UNKNOWN, NULL, tag, arg );
    1014938
    1015939    return 0;
     
    1063987}
    1064988
    1065 static int
    1066 gotmsg( struct ipc_info * info, tr_benc * name, tr_benc * val,
    1067         tr_benc * tagval, void * arg )
    1068 {
    1069     struct msgfunc key, * handler;
    1070     struct msg   * msg;
    1071     int64_t        tag;
    1072 
    1073     if( TYPE_STR != name->type )
    1074     {
    1075         errno = EINVAL;
    1076         return -1;
    1077     }
    1078 
    1079     if( NULL == tagval )
    1080     {
    1081         tag = -1;
    1082     }
    1083     else
    1084     {
    1085         if( TYPE_INT != tagval->type )
     989ssize_t
     990ipc_parse( struct ipc_info * info, uint8_t * buf, ssize_t total, void * arg )
     991{
     992    char        hex[IPC_MIN_MSG_LEN+1], * end;
     993    ssize_t     off, len;
     994    tr_benc  benc;
     995
     996    for( off = 0; off + IPC_MIN_MSG_LEN < total; off += IPC_MIN_MSG_LEN + len )
     997    {
     998        memcpy( hex, buf + off, IPC_MIN_MSG_LEN );
     999        hex[IPC_MIN_MSG_LEN] = '\0';
     1000        end = NULL;
     1001        len = strtol( hex, &end, 16 );
     1002        if( hex + IPC_MIN_MSG_LEN != end ||
     1003            0 > len || IPC_MAX_MSG_LEN < len )
    10861004        {
    10871005            errno = EINVAL;
    10881006            return -1;
    10891007        }
    1090         tag = tagval->val.i;
    1091     }
    1092 
    1093     msg = msglookup( name->val.s.s );
    1094     if( NULL != msg && msg->minvers <= info->vers )
    1095     {
    1096         memset( &key, 0, sizeof key );
    1097         key.id  = msg->id;
    1098         handler = RB_FIND( functree, &info->funcs->msgs, &key );
    1099         if( NULL != handler )
    1100         {
    1101             handler->func( msg->id, val, tag, arg );
    1102         }
    1103         else if( NULL != info->funcs->def )
    1104         {
    1105             info->funcs->def( msg->id, val, tag, arg );
    1106         }
    1107     }
    1108     else if( NULL != info->funcs->def )
    1109         info->funcs->def( IPC__MSG_UNKNOWN, NULL, tag, arg );
    1110 
    1111     return 0;
     1008        if( off + IPC_MIN_MSG_LEN + len > total )
     1009        {
     1010            break;
     1011        }
     1012        errno = 0;
     1013        if( tr_bencLoad( buf + off + IPC_MIN_MSG_LEN, len, &benc, NULL ) )
     1014        {
     1015            if( 0 == errno )
     1016            {
     1017                errno = EINVAL;
     1018            }
     1019            return -1;
     1020        }
     1021        if( 0 > ( HASVERS( info ) ? handlemsgs( info, &benc, arg ) :
     1022                                    handlevers( info, &benc ) ) )
     1023        {
     1024            SAFEBENCFREE( &benc );
     1025            return -1;
     1026        }
     1027        tr_bencFree( &benc );
     1028    }
     1029
     1030    return off;
    11121031}
    11131032
     
    11181037    assert( HASVERS( info ) );
    11191038
    1120     return ( gl_msgs[id].minvers <= info->vers );
     1039    return gl_msgs[id].minvers <= info->vers;
    11211040}
    11221041
     
    11241043ipc_msgid( struct ipc_info * info, const char * name )
    11251044{
    1126     struct msg * msg;
    1127 
    1128     msg = msglookup( name );
    1129     if( NULL == msg || !ipc_havemsg( info, msg->id ) )
    1130     {
    1131         return IPC__MSG_COUNT;
    1132     }
    1133 
    1134     return msg->id;
     1045    const struct msg * msg = msglookup( name );
     1046
     1047    return msg && ipc_havemsg( info, msg->id )
     1048        ? msg->id
     1049        : IPC__MSG_COUNT;
    11351050}
    11361051
     
    11381053ipc_ishandled( struct ipc_info * info, enum ipc_msg id )
    11391054{
    1140     struct msgfunc key;
    1141 
    11421055    assert( MSGVALID( id ) );
    11431056
    1144     memset( &key, 0, sizeof key );
    1145     key.id = id;
    1146     return ( NULL != RB_FIND( functree, &info->funcs->msgs, &key ) );
     1057    return info->funcs->msgs[id] != NULL;
    11471058}
    11481059
     
    11531064}
    11541065
     1066static int
     1067compareNameToInf( const void * a, const void * b )
     1068{
     1069    const struct inf * inf = b;
     1070    return strcmp( a, inf->name );
     1071}
     1072
    11551073int
    1156 ipc_infotypes( enum ipc_msg id, tr_benc * list )
    1157 {
    1158     static struct inftree infotree = RB_INITIALIZER( &tree );
    1159     static struct inftree stattree = RB_INITIALIZER( &tree );
    1160     struct inftree * tree;
    1161     tr_benc     * name;
    1162     struct inf     * array, * inf, key;
    1163     size_t           len, ii;
    1164     int              ret, jj;
     1074ipc_infotypes( enum ipc_msg id, const tr_benc * list )
     1075{
     1076    const struct inf     * array;
     1077    size_t                 len;
     1078    int                    i;
     1079    int                    ret;
    11651080
    11661081    switch( id )
    11671082    {
    11681083        case IPC_MSG_INFO:
    1169             tree  = &infotree;
    11701084            array = gl_inf;
    1171             len   = ARRAYLEN( gl_inf );
     1085            len   = TR_N_ELEMENTS( gl_inf );
    11721086            break;
    11731087        case IPC_MSG_STAT:
    1174             tree  = &stattree;
    11751088            array = gl_stat;
    1176             len   = ARRAYLEN( gl_stat );
     1089            len   = TR_N_ELEMENTS( gl_stat );
    11771090            break;
    11781091        default:
     
    11811094    }
    11821095
    1183     if( RB_EMPTY( tree ) )
    1184     {
    1185         for( ii = 0; len > ii; ii++ )
    1186         {
    1187             assert( 1 << ii == array[ii].type );
    1188             inf = RB_INSERT( inftree, tree, &array[ii] );
    1189             assert( NULL == inf );
    1190         }
    1191     }
    1192 
    11931096    ret = IPC_INF_ID;
    11941097
     
    11981101    }
    11991102
    1200     memset( &key, 0, sizeof key );
    1201     for( jj = 0; list->val.l.count > jj; jj++ )
    1202     {
    1203         name = &list->val.l.vals[jj];
     1103    for( i=0; i<list->val.l.count; ++i )
     1104    {
     1105        const tr_benc * name = &list->val.l.vals[i];
     1106        const struct inf * inf;
     1107
    12041108        if( TYPE_STR != name->type )
    1205         {
    12061109            continue;
    1207         }
    1208         key.name = name->val.s.s;
    1209         inf = RB_FIND( inftree, tree, &key );
    1210         if( NULL != inf )
    1211         {
     1110
     1111        inf = bsearch( name->val.s.s,
     1112                       array, len, sizeof( struct inf ),
     1113                       compareNameToInf );
     1114        if( inf )
    12121115            ret |= inf->type;
    1213         }
    12141116    }
    12151117
     
    12201122ipc_infoname( enum ipc_msg id, int type )
    12211123{
    1222     struct inf * array;
     1124    const struct inf * array;
    12231125    size_t len, ii;
    12241126
     
    12271129        case IPC_MSG_INFO:
    12281130            array = gl_inf;
    1229             len   = ARRAYLEN( gl_inf );
     1131            len   = TR_N_ELEMENTS( gl_inf );
    12301132            break;
    12311133        case IPC_MSG_STAT:
    12321134            array = gl_stat;
    1233             len   = ARRAYLEN( gl_stat );
     1135            len   = TR_N_ELEMENTS( gl_stat );
    12341136            break;
    12351137        default:
     
    12391141
    12401142    for( ii = 0; len > ii; ii++ )
    1241     {
    12421143        if( array[ii].type == type )
    1243         {
    12441144            return array[ii].name;
    1245         }
    1246     }
    12471145
    12481146    assert( 0 );
    1249 
    12501147    return NULL;
    12511148}
    1252 
    1253 static int
    1254 msgcmp( struct msg * first, struct msg * second )
    1255 {
    1256     return strcmp( first->name, second->name );
    1257 }
    1258 
    1259 static int
    1260 infcmp( struct inf * first, struct inf * second )
    1261 {
    1262     return strcmp( first->name, second->name );
    1263 }
    1264 
    1265 static struct msg *
    1266 msglookup( const char * name )
    1267 {
    1268     static struct msgtree tree = RB_INITIALIZER( &tree );
    1269     struct msg          * ret, key;
    1270     size_t                ii;
    1271 
    1272     assert( IPC__MSG_COUNT == ARRAYLEN( gl_msgs ) );
    1273 
    1274     if( RB_EMPTY( &tree ) )
    1275     {
    1276         for( ii = 0; ARRAYLEN( gl_msgs ) > ii; ii++ )
    1277         {
    1278             assert( ii == gl_msgs[ii].id );
    1279             ret = RB_INSERT( msgtree, &tree, &gl_msgs[ii] );
    1280             assert( NULL == ret );
    1281         }
    1282     }
    1283 
    1284     memset( &key, 0, sizeof key );
    1285     key.name = name;
    1286     return RB_FIND( msgtree, &tree, &key );
    1287 }
    1288 
    1289 static int
    1290 filltracker( tr_benc * val, const tr_tracker_info * tk )
    1291 {
    1292     tr_bencInit( val, TYPE_DICT );
    1293     if( tr_bencDictReserve( val, ( NULL == tk->scrape ? 3 : 4 ) ) )
    1294     {
    1295         return -1;
    1296     }
    1297 
    1298     tr_bencInitStr( tr_bencDictAdd( val, "address" ),  tk->address,  -1, 1 );
    1299     tr_bencInitInt( tr_bencDictAdd( val, "port" ),     tk->port );
    1300     tr_bencInitStr( tr_bencDictAdd( val, "announce" ), tk->announce, -1, 1 );
    1301     if( NULL != tk->scrape )
    1302     {
    1303         tr_bencInitStr( tr_bencDictAdd( val, "scrape" ), tk->scrape, -1, 1 );
    1304     }
    1305 
    1306     return 0;
    1307 }
  • trunk/libtransmission/ipcparse.h

    r5127 r5137  
    3232#define IPC_MAX_MSG_LEN         ( 0x7fffffff - IPC_MIN_MSG_LEN )
    3333
     34/* These need to be in the same order as ipcparse.c's gl_msgs array. */
    3435enum ipc_msg
    3536{
    36     IPC_MSG_ADDMANYFILES = 0,
    37     IPC_MSG_ADDONEFILE,
     37    IPC_MSG_ADDONEFILE = 0,
     38    IPC_MSG_ADDMANYFILES,
    3839    IPC_MSG_AUTOMAP,
    3940    IPC_MSG_AUTOSTART,
    4041    IPC_MSG_BAD,
    41     IPC_MSG_CRYPTO,
    4242    IPC_MSG_DIR,
    4343    IPC_MSG_DOWNLIMIT,
     44    IPC_MSG_CRYPTO,
    4445    IPC_MSG_FAIL,
    4546    IPC_MSG_GETAUTOMAP,
    4647    IPC_MSG_GETAUTOSTART,
    47     IPC_MSG_GETCRYPTO,
    4848    IPC_MSG_GETDIR,
    4949    IPC_MSG_GETDOWNLIMIT,
     50    IPC_MSG_GETCRYPTO,
    5051    IPC_MSG_GETINFO,
    5152    IPC_MSG_GETINFOALL,
     
    5657    IPC_MSG_GETSUP,
    5758    IPC_MSG_GETUPLIMIT,
     59    IPC_MSG_INFO,
    5860    IPC_MSG_LOOKUP,
    59     IPC_MSG_INFO,
    6061    IPC_MSG_NOOP,
    6162    IPC_MSG_NOTSUP,
     
    7879};
    7980
    80 /* If you add or delete a constant here then you need to renumber the
    81    ones after it. They need to be in ascending order starting at zero,
    82    with no gaps. */
     81/* If you add or delete a constant here, to renumber the ones after it.
     82 * They need to be in ascending order starting at zero, with no gaps.
     83 * They also need to be in the same order as ipcparse.c's gl_inf array. */
    8384#define IPC_INF_COMMENT         ( 1 << 0 )
    8485#define IPC_INF_CREATOR         ( 1 << 1 )
     
    9495#define IPC_INF__MAX            ( 1 << 11 )
    9596
    96 /* Ditto for these */
     97/* If you add or delete a constant here, to renumber the ones after it.
     98 * They need to be in ascending order starting at zero, with no gaps.
     99 * They also need to be in the same order as ipcparse.c's gl_stat array. */
    97100#define IPC_ST_COMPLETED        ( 1 << 0 )
    98101#define IPC_ST_DOWNSPEED        ( 1 << 1 )
     
    108111#define IPC_ST_PEERUP           ( 1 << 11 )
    109112#define IPC_ST_RUNNING          ( 1 << 12 )
    110 #define IPC_ST_STATE            ( 1 << 13 )
    111 #define IPC_ST_SWARM            ( 1 << 14 )
    112 #define IPC_ST_TRACKER          ( 1 << 15 )
    113 #define IPC_ST_TKDONE           ( 1 << 16 )
    114 #define IPC_ST_TKLEECH          ( 1 << 17 )
    115 #define IPC_ST_TKSEED           ( 1 << 18 )
     113#define IPC_ST_TKDONE           ( 1 << 13 )
     114#define IPC_ST_TKLEECH          ( 1 << 14 )
     115#define IPC_ST_TKSEED           ( 1 << 15 )
     116#define IPC_ST_STATE            ( 1 << 16 )
     117#define IPC_ST_SWARM            ( 1 << 17 )
     118#define IPC_ST_TRACKER          ( 1 << 18 )
    116119#define IPC_ST_UPSPEED          ( 1 << 19 )
    117120#define IPC_ST_UPTOTAL          ( 1 << 20 )
     
    133136
    134137#define HASVERS( info )         ( 0 < (info)->vers )
    135 #define VERSLABEL( info )       ( (info)->label )
    136 
    137138#define TORRENT_ID_VALID( id )  ( 0 < (id) && INT_MAX > (id) )
    138139
     
    144145/* setup */
    145146struct ipc_funcs * ipc_initmsgs ( void );
    146 int          ipc_addmsg   ( struct ipc_funcs *, enum ipc_msg, trd_msgfunc );
     147void         ipc_addmsg   ( struct ipc_funcs *, enum ipc_msg, trd_msgfunc );
    147148void         ipc_setdefmsg( struct ipc_funcs *, trd_msgfunc );
    148149void         ipc_freemsgs ( struct ipc_funcs * );
     
    154155struct tr_benc * ipc_initval  ( struct ipc_info *, enum ipc_msg, int64_t,
    155156                            struct tr_benc *, int );
    156 uint8_t *    ipc_mkval    ( struct tr_benc *, size_t * );
     157uint8_t *    ipc_mkval    ( const struct tr_benc *, size_t * );
    157158uint8_t *    ipc_mkempty  ( struct ipc_info *, size_t *, enum ipc_msg,
    158159                            int64_t );
     
    176177int          ipc_ishandled( struct ipc_info *, enum ipc_msg );
    177178int          ipc_havetags ( struct ipc_info * );
    178 int          ipc_infotypes( enum ipc_msg, struct tr_benc * );
     179int          ipc_infotypes( enum ipc_msg, const struct tr_benc * );
    179180const char * ipc_infoname ( enum ipc_msg, int );
    180181
  • trunk/macosx/IPCController.m

    r4552 r5137  
    146146        nil  == _listen  ||
    147147        NULL == _funcs   ||
    148         nil  == _clients ||
    149         0 > ipc_addmsg( _funcs, IPC_MSG_ADDMANYFILES, msg_addold    ) ||
    150         0 > ipc_addmsg( _funcs, IPC_MSG_ADDONEFILE,   msg_addnew    ) ||
    151         0 > ipc_addmsg( _funcs, IPC_MSG_AUTOMAP,      msg_setbool   ) ||
    152         0 > ipc_addmsg( _funcs, IPC_MSG_AUTOSTART,    msg_setbool   ) ||
    153         0 > ipc_addmsg( _funcs, IPC_MSG_CRYPTO,       msg_setstr    ) ||
    154         0 > ipc_addmsg( _funcs, IPC_MSG_DIR,          msg_setstr    ) ||
    155         0 > ipc_addmsg( _funcs, IPC_MSG_DOWNLIMIT,    msg_setint    ) ||
    156         0 > ipc_addmsg( _funcs, IPC_MSG_GETAUTOMAP,   msg_getbool   ) ||
    157         0 > ipc_addmsg( _funcs, IPC_MSG_GETAUTOSTART, msg_getbool   ) ||
    158         0 > ipc_addmsg( _funcs, IPC_MSG_GETCRYPTO,    msg_getstr    ) ||
    159         0 > ipc_addmsg( _funcs, IPC_MSG_GETDIR,       msg_getstr    ) ||
    160         0 > ipc_addmsg( _funcs, IPC_MSG_GETDOWNLIMIT, msg_getint    ) ||
    161         0 > ipc_addmsg( _funcs, IPC_MSG_GETINFO,      msg_info      ) ||
    162         0 > ipc_addmsg( _funcs, IPC_MSG_GETINFOALL,   msg_infoall   ) ||
    163         0 > ipc_addmsg( _funcs, IPC_MSG_GETPEX,       msg_getbool   ) ||
    164         0 > ipc_addmsg( _funcs, IPC_MSG_GETPORT,      msg_getint    ) ||
    165         0 > ipc_addmsg( _funcs, IPC_MSG_GETSTAT,      msg_info      ) ||
    166         0 > ipc_addmsg( _funcs, IPC_MSG_GETSTATALL,   msg_infoall   ) ||
    167         0 > ipc_addmsg( _funcs, IPC_MSG_GETUPLIMIT,   msg_getint    ) ||
    168         0 > ipc_addmsg( _funcs, IPC_MSG_LOOKUP,       msg_lookup    ) ||
    169         0 > ipc_addmsg( _funcs, IPC_MSG_NOOP,         msg_empty     ) ||
    170         0 > ipc_addmsg( _funcs, IPC_MSG_PEX,          msg_setbool   ) ||
    171         0 > ipc_addmsg( _funcs, IPC_MSG_PORT,         msg_setint    ) ||
    172         0 > ipc_addmsg( _funcs, IPC_MSG_QUIT,         msg_empty     ) ||
    173         0 > ipc_addmsg( _funcs, IPC_MSG_REMOVE,       msg_action    ) ||
    174         0 > ipc_addmsg( _funcs, IPC_MSG_REMOVEALL,    msg_actionall ) ||
    175         0 > ipc_addmsg( _funcs, IPC_MSG_START,        msg_action    ) ||
    176         0 > ipc_addmsg( _funcs, IPC_MSG_STARTALL,     msg_actionall ) ||
    177         0 > ipc_addmsg( _funcs, IPC_MSG_STOP,         msg_action    ) ||
    178         0 > ipc_addmsg( _funcs, IPC_MSG_STOPALL,      msg_actionall ) ||
    179         0 > ipc_addmsg( _funcs, IPC_MSG_SUP,          msg_sup       ) ||
    180         0 > ipc_addmsg( _funcs, IPC_MSG_UPLIMIT,      msg_setint    ) )
     148        nil  == _clients )
    181149    {
    182150        [self release];
    183151        return nil;
    184152    }
     153
     154    ipc_addmsg( _funcs, IPC_MSG_ADDMANYFILES, msg_addold    );
     155    ipc_addmsg( _funcs, IPC_MSG_ADDONEFILE,   msg_addnew    );
     156    ipc_addmsg( _funcs, IPC_MSG_AUTOMAP,      msg_setbool   );
     157    ipc_addmsg( _funcs, IPC_MSG_AUTOSTART,    msg_setbool   );
     158    ipc_addmsg( _funcs, IPC_MSG_CRYPTO,       msg_setstr    );
     159    ipc_addmsg( _funcs, IPC_MSG_DIR,          msg_setstr    );
     160    ipc_addmsg( _funcs, IPC_MSG_DOWNLIMIT,    msg_setint    );
     161    ipc_addmsg( _funcs, IPC_MSG_GETAUTOMAP,   msg_getbool   );
     162    ipc_addmsg( _funcs, IPC_MSG_GETAUTOSTART, msg_getbool   );
     163    ipc_addmsg( _funcs, IPC_MSG_GETCRYPTO,    msg_getstr    );
     164    ipc_addmsg( _funcs, IPC_MSG_GETDIR,       msg_getstr    );
     165    ipc_addmsg( _funcs, IPC_MSG_GETDOWNLIMIT, msg_getint    );
     166    ipc_addmsg( _funcs, IPC_MSG_GETINFO,      msg_info      );
     167    ipc_addmsg( _funcs, IPC_MSG_GETINFOALL,   msg_infoall   );
     168    ipc_addmsg( _funcs, IPC_MSG_GETPEX,       msg_getbool   );
     169    ipc_addmsg( _funcs, IPC_MSG_GETPORT,      msg_getint    );
     170    ipc_addmsg( _funcs, IPC_MSG_GETSTAT,      msg_info      );
     171    ipc_addmsg( _funcs, IPC_MSG_GETSTATALL,   msg_infoall   );
     172    ipc_addmsg( _funcs, IPC_MSG_GETUPLIMIT,   msg_getint    );
     173    ipc_addmsg( _funcs, IPC_MSG_LOOKUP,       msg_lookup    );
     174    ipc_addmsg( _funcs, IPC_MSG_NOOP,         msg_empty     );
     175    ipc_addmsg( _funcs, IPC_MSG_PEX,          msg_setbool   );
     176    ipc_addmsg( _funcs, IPC_MSG_PORT,         msg_setint    );
     177    ipc_addmsg( _funcs, IPC_MSG_QUIT,         msg_empty     );
     178    ipc_addmsg( _funcs, IPC_MSG_REMOVE,       msg_action    );
     179    ipc_addmsg( _funcs, IPC_MSG_REMOVEALL,    msg_actionall );
     180    ipc_addmsg( _funcs, IPC_MSG_START,        msg_action    );
     181    ipc_addmsg( _funcs, IPC_MSG_STARTALL,     msg_actionall );
     182    ipc_addmsg( _funcs, IPC_MSG_STOP,         msg_action    );
     183    ipc_addmsg( _funcs, IPC_MSG_STOPALL,      msg_actionall );
     184    ipc_addmsg( _funcs, IPC_MSG_SUP,          msg_sup       );
     185    ipc_addmsg( _funcs, IPC_MSG_UPLIMIT,      msg_setint    );
    185186    ipc_setdefmsg( _funcs, msg_default );
    186187
Note: See TracChangeset for help on using the changeset viewer.