Changeset 1039

Show
Ignore:
Timestamp:
02/22/08 09:11:40 (4 years ago)
Author:
rakshasa
Message:

* Added system.time{,_seconds,_usec} commands.

* Cleaned up XMLRPC handling and added support for empty targets so it
will handle print and cat properly.

Location:
trunk
Files:
6 modified

Legend:

Unmodified
Added
Removed
  • trunk/libtorrent/rak/timer.h

    r955 r1039  
    6464 
    6565  static timer        current(); 
     66  static int64_t      current_seconds()                   { return current().seconds(); } 
     67  static int64_t      current_usec()                      { return current().usec(); } 
    6668  static timer        from_seconds(uint32_t seconds)      { return rak::timer((uint64_t)seconds * 1000000); } 
    6769  static timer        from_milliseconds(uint32_t seconds) { return rak::timer((uint64_t)seconds * 1000); } 
  • trunk/rtorrent/rak/timer.h

    r955 r1039  
    6464 
    6565  static timer        current(); 
     66  static int64_t      current_seconds()                   { return current().seconds(); } 
     67  static int64_t      current_usec()                      { return current().usec(); } 
    6668  static timer        from_seconds(uint32_t seconds)      { return rak::timer((uint64_t)seconds * 1000000); } 
    6769  static timer        from_milliseconds(uint32_t seconds) { return rak::timer((uint64_t)seconds * 1000); } 
  • trunk/rtorrent/src/command_events.cc

    r1026 r1039  
    214214torrent::Object 
    215215apply_load(int flags, const torrent::Object& rawArgs) { 
    216   const torrent::Object::list_type&          args    = rawArgs.as_list(); 
     216  const torrent::Object::list_type&    args    = rawArgs.as_list(); 
    217217  torrent::Object::list_const_iterator argsItr = args.begin(); 
    218218 
  • trunk/rtorrent/src/command_local.cc

    r1025 r1039  
    132132  ADD_COMMAND_VOID("system.file_status_cache.prune", rak::make_mem_fun(control->core()->file_status_cache(), &utils::FileStatusCache::prune)); 
    133133 
    134   ADD_COMMAND_VALUE_SET_OCT("system.", "umask",  std::ptr_fun(&umask)); 
    135   ADD_COMMAND_STRING_PREFIX("system.", "cwd",    std::ptr_fun(system_set_cwd), rak::ptr_fun(&system_get_cwd)); 
     134  ADD_COMMAND_VOID("system.time",                    rak::make_mem_fun(&cachedTime, &rak::timer::seconds)); 
     135  ADD_COMMAND_VOID("system.time_seconds",            rak::ptr_fun(&rak::timer::current_seconds)); 
     136  ADD_COMMAND_VOID("system.time_usec",               rak::ptr_fun(&rak::timer::current_usec)); 
     137 
     138  ADD_COMMAND_VALUE_SET_OCT("system.", "umask",      std::ptr_fun(&umask)); 
     139  ADD_COMMAND_STRING_PREFIX("system.", "cwd",        std::ptr_fun(system_set_cwd), rak::ptr_fun(&system_get_cwd)); 
    136140 
    137141  ADD_VARIABLE_STRING("name", ""); 
     
    141145  ADD_VARIABLE_STRING("split_suffix", ".part"); 
    142146 
    143   ADD_COMMAND_VOID("get_memory_usage",           rak::make_mem_fun(chunkManager, &CM_t::memory_usage)); 
    144   ADD_COMMAND_VALUE_TRI("max_memory_usage",      rak::make_mem_fun(chunkManager, &CM_t::set_max_memory_usage), rak::make_mem_fun(chunkManager, &CM_t::max_memory_usage)); 
    145   ADD_COMMAND_VALUE_TRI("safe_sync",             rak::make_mem_fun(chunkManager, &CM_t::set_safe_sync), rak::make_mem_fun(chunkManager, &CM_t::safe_sync)); 
    146   ADD_COMMAND_VOID("get_safe_free_diskspace",    rak::make_mem_fun(chunkManager, &CM_t::safe_free_diskspace)); 
    147   ADD_COMMAND_VALUE_TRI("timeout_sync",          rak::make_mem_fun(chunkManager, &CM_t::set_timeout_sync), rak::make_mem_fun(chunkManager, &CM_t::timeout_sync)); 
    148   ADD_COMMAND_VALUE_TRI("timeout_safe_sync",     rak::make_mem_fun(chunkManager, &CM_t::set_timeout_safe_sync), rak::make_mem_fun(chunkManager, &CM_t::timeout_safe_sync)); 
     147  ADD_COMMAND_VOID("get_memory_usage",               rak::make_mem_fun(chunkManager, &CM_t::memory_usage)); 
     148  ADD_COMMAND_VALUE_TRI("max_memory_usage",          rak::make_mem_fun(chunkManager, &CM_t::set_max_memory_usage), rak::make_mem_fun(chunkManager, &CM_t::max_memory_usage)); 
     149  ADD_COMMAND_VALUE_TRI("safe_sync",                 rak::make_mem_fun(chunkManager, &CM_t::set_safe_sync), rak::make_mem_fun(chunkManager, &CM_t::safe_sync)); 
     150  ADD_COMMAND_VOID("get_safe_free_diskspace",        rak::make_mem_fun(chunkManager, &CM_t::safe_free_diskspace)); 
     151  ADD_COMMAND_VALUE_TRI("timeout_sync",              rak::make_mem_fun(chunkManager, &CM_t::set_timeout_sync), rak::make_mem_fun(chunkManager, &CM_t::timeout_sync)); 
     152  ADD_COMMAND_VALUE_TRI("timeout_safe_sync",         rak::make_mem_fun(chunkManager, &CM_t::set_timeout_safe_sync), rak::make_mem_fun(chunkManager, &CM_t::timeout_safe_sync)); 
    149153 
    150   ADD_COMMAND_VALUE_TRI("preload_type",          rak::make_mem_fun(chunkManager, &CM_t::set_preload_type), rak::make_mem_fun(chunkManager, &CM_t::preload_type)); 
    151   ADD_COMMAND_VALUE_TRI("preload_min_size",      rak::make_mem_fun(chunkManager, &CM_t::set_preload_min_size), rak::make_mem_fun(chunkManager, &CM_t::preload_min_size)); 
    152   ADD_COMMAND_VALUE_TRI_KB("preload_required_rate", rak::make_mem_fun(chunkManager, &CM_t::set_preload_required_rate), rak::make_mem_fun(chunkManager, &CM_t::preload_required_rate)); 
     154  ADD_COMMAND_VALUE_TRI("preload_type",              rak::make_mem_fun(chunkManager, &CM_t::set_preload_type), rak::make_mem_fun(chunkManager, &CM_t::preload_type)); 
     155  ADD_COMMAND_VALUE_TRI("preload_min_size",          rak::make_mem_fun(chunkManager, &CM_t::set_preload_min_size), rak::make_mem_fun(chunkManager, &CM_t::preload_min_size)); 
     156  ADD_COMMAND_VALUE_TRI_KB("preload_required_rate",  rak::make_mem_fun(chunkManager, &CM_t::set_preload_required_rate), rak::make_mem_fun(chunkManager, &CM_t::preload_required_rate)); 
    153157 
    154   ADD_COMMAND_VOID("get_stats_preloaded",        rak::make_mem_fun(chunkManager, &CM_t::stats_preloaded)); 
    155   ADD_COMMAND_VOID("get_stats_not_preloaded",    rak::make_mem_fun(chunkManager, &CM_t::stats_not_preloaded)); 
     158  ADD_COMMAND_VOID("get_stats_preloaded",            rak::make_mem_fun(chunkManager, &CM_t::stats_preloaded)); 
     159  ADD_COMMAND_VOID("get_stats_not_preloaded",        rak::make_mem_fun(chunkManager, &CM_t::stats_not_preloaded)); 
    156160 
    157161  ADD_VARIABLE_STRING("directory", "./"); 
  • trunk/rtorrent/src/command_ui.cc

    r1038 r1039  
    146146 
    147147torrent::Object 
    148 apply_to_date(const torrent::Object& rawArgs) { 
     148apply_to_time(int flags, const torrent::Object& rawArgs) { 
     149  std::tm *u; 
    149150  time_t t = (uint64_t)rawArgs.as_value(); 
    150   std::tm *u = std::gmtime(&t); 
     151 
     152  if (flags & 0x1) 
     153    u = std::localtime(&t); 
     154  else 
     155    u = std::gmtime(&t); 
    151156   
    152157  if (u == NULL) 
     
    154159 
    155160  char buffer[11]; 
    156   snprintf(buffer, 11, "%02u/%02u/%04u", u->tm_mday, (u->tm_mon + 1), (1900 + u->tm_year)); 
    157    
    158   return std::string(buffer); 
    159 } 
    160  
    161 torrent::Object 
    162 apply_to_time(const torrent::Object& rawArgs) { 
    163   time_t t = (uint64_t)rawArgs.as_value(); 
    164   std::tm *u = std::gmtime(&t); 
    165    
    166   if (u == NULL) 
    167     return torrent::Object(); 
    168  
    169   char buffer[9]; 
    170   snprintf(buffer, 9, "%2d:%02d:%02d", u->tm_hour, u->tm_min, u->tm_sec); 
     161 
     162  if (flags & 0x2) 
     163    snprintf(buffer, 11, "%02u/%02u/%04u", u->tm_mday, (u->tm_mon + 1), (1900 + u->tm_year)); 
     164  else 
     165    snprintf(buffer, 9, "%2d:%02d:%02d", u->tm_hour, u->tm_min, u->tm_sec); 
    171166 
    172167  return std::string(buffer); 
     
    312307  ADD_ANY_NONE("branch",                rak::bind_ptr_fn(&apply_if, 1)); 
    313308 
    314   ADD_COMMAND_VALUE("to_date",          rak::ptr_fn(&apply_to_date)); 
    315   ADD_COMMAND_VALUE("to_time",          rak::ptr_fn(&apply_to_time)); 
     309  ADD_COMMAND_VALUE("to_gm_time",       rak::bind_ptr_fn(&apply_to_time, 0)); 
     310  ADD_COMMAND_VALUE("to_gm_date",       rak::bind_ptr_fn(&apply_to_time, 0x2)); 
     311  ADD_COMMAND_VALUE("to_time",          rak::bind_ptr_fn(&apply_to_time, 0x1)); 
     312  ADD_COMMAND_VALUE("to_date",          rak::bind_ptr_fn(&apply_to_time, 0x1 | 0x2)); 
    316313  ADD_COMMAND_VALUE("to_elapsed_time",  rak::ptr_fn(&apply_to_elapsed_time)); 
    317314  ADD_COMMAND_VALUE("to_kb",            rak::ptr_fn(&apply_to_kb)); 
  • trunk/rtorrent/src/rpc/xmlrpc.cc

    r1026 r1039  
    5252#ifdef HAVE_XMLRPC_C 
    5353 
     54class xmlrpc_error : public torrent::base_error { 
     55public: 
     56  xmlrpc_error(xmlrpc_env* env) : m_type(env->fault_code), m_msg(env->fault_string) {} 
     57  xmlrpc_error(int type, char* msg) : m_type(type), m_msg(msg) {} 
     58  virtual ~xmlrpc_error() throw() {} 
     59 
     60  virtual int         type() const throw() { return m_type; } 
     61  virtual const char* what() const throw() { return m_msg; } 
     62 
     63private: 
     64  int                 m_type; 
     65  char*               m_msg; 
     66}; 
     67 
     68torrent::Object xmlrpc_to_object(xmlrpc_env* env, xmlrpc_value* value, int callType = 0, rpc::target_type* target = NULL); 
     69 
     70inline torrent::Object 
     71xmlrpc_list_entry_to_object(xmlrpc_env* env, xmlrpc_value* src, int index) { 
     72  xmlrpc_value* tmp; 
     73  xmlrpc_array_read_item(env, src, index, &tmp); 
     74 
     75  if (env->fault_occurred) 
     76    throw xmlrpc_error(env); 
     77 
     78  torrent::Object obj = xmlrpc_to_object(env, tmp); 
     79  xmlrpc_DECREF(tmp); 
     80 
     81  return obj; 
     82} 
     83 
     84int64_t 
     85xmlrpc_list_entry_to_value(xmlrpc_env* env, xmlrpc_value* src, int index) { 
     86  xmlrpc_value* tmp; 
     87  xmlrpc_array_read_item(env, src, index, &tmp); 
     88 
     89  if (env->fault_occurred) 
     90    throw xmlrpc_error(env); 
     91 
     92  switch (xmlrpc_value_type(tmp)) { 
     93  case XMLRPC_TYPE_INT: 
     94    int v; 
     95    xmlrpc_read_int(env, tmp, &v); 
     96    xmlrpc_DECREF(tmp); 
     97    return v; 
     98 
     99#ifdef XMLRPC_HAVE_I8 
     100  case XMLRPC_TYPE_I8: 
     101    long long v2; 
     102    xmlrpc_read_i8(env, tmp, &v2); 
     103    xmlrpc_DECREF(tmp); 
     104    return v2; 
     105#endif 
     106 
     107  case XMLRPC_TYPE_STRING: 
     108  { 
     109    const char* str; 
     110    xmlrpc_read_string(env, tmp, &str); 
     111 
     112    if (env->fault_occurred) 
     113      throw xmlrpc_error(env); 
     114 
     115    const char* end = str; 
     116    int64_t v3 = ::strtoll(str, (char**)&end, 0); 
     117 
     118    ::free((void*)str); 
     119 
     120    if (*str == '\0' || *end != '\0') 
     121      throw xmlrpc_error(XMLRPC_TYPE_ERROR, "Invalid index."); 
     122 
     123    return v3; 
     124  } 
     125 
     126  default: 
     127    xmlrpc_DECREF(tmp); 
     128    throw xmlrpc_error(XMLRPC_TYPE_ERROR, "Invalid type found."); 
     129  } 
     130} 
     131 
     132// Consider making a helper function that creates a target_type from a 
     133// torrent::Object, then we can just use xmlrpc_to_object. 
     134rpc::target_type 
     135xmlrpc_to_target(xmlrpc_env* env, xmlrpc_value* value) { 
     136  switch (xmlrpc_value_type(value)) { 
     137  case XMLRPC_TYPE_STRING: 
     138    const char* str; 
     139    xmlrpc_read_string(env, value, &str); 
     140 
     141    if (env->fault_occurred) 
     142      throw xmlrpc_error(env); 
     143 
     144    if (std::strlen(str) == 40) { 
     145      core::Download* download = xmlrpc.get_slot_find_download()(str); 
     146      ::free((void*)str); 
     147 
     148      if (download == NULL) 
     149        throw xmlrpc_error(XMLRPC_TYPE_ERROR, "Could not find info-hash."); 
     150 
     151      return rpc::make_target(download); 
     152 
     153    } else if (std::strlen(str) == 0) { 
     154      ::free((void*)str); 
     155      return rpc::make_target(); 
     156    } 
     157 
     158    ::free((void*)str); 
     159    throw xmlrpc_error(XMLRPC_TYPE_ERROR, "Unsupported target type found."); 
     160 
     161  default: 
     162    return rpc::make_target(); 
     163  } 
     164} 
     165 
     166rpc::target_type 
     167xmlrpc_to_index_type(int index, int callType, core::Download* download) { 
     168  void* result; 
     169 
     170  switch (callType) { 
     171  case XmlRpc::call_file:    result = xmlrpc.get_slot_find_file()(download, index); break; 
     172  case XmlRpc::call_tracker: result = xmlrpc.get_slot_find_tracker()(download, index); break; 
     173  default: result = NULL; break; 
     174  } 
     175 
     176  if (result == NULL) 
     177    throw xmlrpc_error(XMLRPC_TYPE_ERROR, "Invalid index."); 
     178       
     179  return rpc::make_target(callType, result); 
     180} 
     181 
    54182torrent::Object 
    55 xmlrpc_to_object(xmlrpc_env* env, xmlrpc_value* value) { 
     183xmlrpc_to_object(xmlrpc_env* env, xmlrpc_value* value, int callType, rpc::target_type* target) { 
    56184  switch (xmlrpc_value_type(value)) { 
    57185  case XMLRPC_TYPE_INT: 
     
    74202 
    75203  case XMLRPC_TYPE_STRING: 
    76   { 
    77     const char* valueString; 
    78     xmlrpc_read_string(env, value, &valueString); 
    79  
    80     if (env->fault_occurred) 
     204 
     205    if (callType != XmlRpc::call_generic) { 
     206      // When the call type is not supposed to be void, we'll try to 
     207      // convert it to a command target. It's not that important that 
     208      // it is converted to the right type here, as an mismatch will 
     209      // be caught when executing the command. 
     210      *target = xmlrpc_to_target(env, value); 
    81211      return torrent::Object(); 
    82212 
    83     torrent::Object result = torrent::Object(std::string(valueString)); 
    84  
    85     // Urgh, seriously? 
    86     ::free((void*)valueString); 
    87     return result; 
    88   } 
     213    } else { 
     214      const char* valueString; 
     215      xmlrpc_read_string(env, value, &valueString); 
     216 
     217      if (env->fault_occurred) 
     218        throw xmlrpc_error(env); 
     219 
     220      torrent::Object result = torrent::Object(std::string(valueString)); 
     221 
     222      // Urgh, seriously? 
     223      ::free((void*)valueString); 
     224      return result; 
     225    } 
    89226 
    90227  case XMLRPC_TYPE_BASE64: 
     
    96233 
    97234    if (env->fault_occurred) 
    98       return torrent::Object(); 
     235      throw xmlrpc_error(env); 
    99236 
    100237    torrent::Object result = torrent::Object(std::string(valueString, valueSize)); 
     
    107244  case XMLRPC_TYPE_ARRAY: 
    108245  { 
    109     torrent::Object result = torrent::Object::create_list(); 
    110     torrent::Object::list_type& listRef = result.as_list(); 
    111  
     246    unsigned int current = 0; 
    112247    unsigned int last = xmlrpc_array_size(env, value); 
    113248 
    114249    if (env->fault_occurred) 
     250      throw xmlrpc_error(env); 
     251 
     252    if (callType != XmlRpc::call_generic) { 
     253      if (last < 1) 
     254        throw xmlrpc_error(XMLRPC_TYPE_ERROR, "Too few arguments."); 
     255 
     256      xmlrpc_value* tmp; 
     257      xmlrpc_array_read_item(env, value, current++, &tmp); 
     258 
     259      if (env->fault_occurred) 
     260        throw xmlrpc_error(env); 
     261 
     262      *target = xmlrpc_to_target(env, tmp); 
     263      xmlrpc_DECREF(tmp); 
     264 
     265      if (env->fault_occurred) 
     266        throw xmlrpc_error(env); 
     267 
     268      if (target->first == XmlRpc::call_download && 
     269          (callType == XmlRpc::call_file || callType == XmlRpc::call_tracker)) { 
     270        // If we have a download target and the call type requires 
     271        // another contained type, then we try to use the next 
     272        // parameter as the index to support old-style calls. 
     273 
     274        if (current == last) 
     275          throw xmlrpc_error(XMLRPC_TYPE_ERROR, "Too few arguments."); 
     276 
     277        *target = xmlrpc_to_index_type(xmlrpc_list_entry_to_value(env, value, current++), callType, (core::Download*)target->second); 
     278      } 
     279    } 
     280 
     281    if (current + 1 < last) { 
     282      torrent::Object result = torrent::Object::create_list(); 
     283      torrent::Object::list_type& listRef = result.as_list(); 
     284 
     285      while (current != last) 
     286        listRef.push_back(xmlrpc_list_entry_to_object(env, value, current++)); 
     287 
     288      return result; 
     289 
     290    } else if (current + 1 == last) { 
     291      return xmlrpc_list_entry_to_object(env, value, current); 
     292 
     293    } else { 
    115294      return torrent::Object(); 
    116  
    117     // Move this into a helper function. 
    118     for (unsigned int i = 0; i != last; i++) { 
    119       // Need to decref. 
    120       xmlrpc_value* tmp; 
    121       xmlrpc_array_read_item(env, value, i, &tmp); 
    122  
    123       if (env->fault_occurred) 
    124         return torrent::Object(); 
    125  
    126       listRef.push_back(xmlrpc_to_object(env, tmp)); 
    127       xmlrpc_DECREF(tmp); 
    128295    } 
    129  
    130     return result; 
    131296  } 
    132297 
     
    136301    //     case XMLRPC_TYPE_DEAD: 
    137302  default: 
    138     xmlrpc_env_set_fault(env, XMLRPC_TYPE_ERROR, "Unsupported type found."); 
    139     return torrent::Object(); 
    140   } 
    141 } 
    142  
    143 core::Download* 
    144 xmlrpc_to_download(xmlrpc_env* env, xmlrpc_value* value) { 
    145   core::Download* download = NULL; 
    146  
    147   switch (xmlrpc_value_type(value)) { 
    148   case XMLRPC_TYPE_STRING: 
    149   { 
    150     const char* str; 
    151     xmlrpc_read_string(env, value, &str); 
    152  
    153     if (env->fault_occurred) 
    154       return NULL; 
    155  
    156     if (std::strlen(str) != 40 || 
    157         (download = xmlrpc.get_slot_find_download()(str)) == NULL) 
    158       xmlrpc_env_set_fault(env, XMLRPC_TYPE_ERROR, "Could not find info-hash."); 
    159  
    160     // Urgh, seriously? 
    161     ::free((void*)str); 
    162     return download; 
    163   } 
    164  
    165   default: 
    166     xmlrpc_env_set_fault(env, XMLRPC_TYPE_ERROR, "Unsupported type found."); 
    167     return NULL; 
    168   } 
    169 } 
    170  
    171 void* 
    172 xmlrpc_to_index_type(xmlrpc_env* env, xmlrpc_value* value, int callType, core::Download* download) { 
    173   int index; 
    174  
    175   switch (xmlrpc_value_type(value)) { 
    176   case XMLRPC_TYPE_INT: 
    177     xmlrpc_read_int(env, value, &index); 
    178     break; 
    179  
    180 #ifdef XMLRPC_HAVE_I8 
    181   case XMLRPC_TYPE_I8: 
    182     long long v2; 
    183     xmlrpc_read_i8(env, value, &v2); 
    184        
    185     index = v2; 
    186     break; 
    187 #endif 
    188  
    189   case XMLRPC_TYPE_STRING: 
    190   { 
    191     const char* str; 
    192     xmlrpc_read_string(env, value, &str); 
    193  
    194     if (env->fault_occurred) 
    195       return NULL; 
    196  
    197     const char* end = str; 
    198     index = ::strtol(str, (char**)&end, 0); 
    199  
    200     ::free((void*)str); 
    201  
    202     if (*str == '\0' || *end != '\0') { 
    203       xmlrpc_env_set_fault(env, XMLRPC_TYPE_ERROR, "Invalid index."); 
    204       return NULL; 
    205     } 
    206  
    207     break; 
    208   } 
    209  
    210   default: 
    211     xmlrpc_env_set_fault(env, XMLRPC_TYPE_ERROR, "Unsupported type found."); 
    212     return NULL; 
    213   } 
    214  
    215   if (env->fault_occurred) 
    216     return NULL; 
    217      
    218   void* result; 
    219  
    220   switch (callType) { 
    221   case XmlRpc::call_file:    result = xmlrpc.get_slot_find_file()(download, index); break; 
    222   case XmlRpc::call_tracker: result = xmlrpc.get_slot_find_tracker()(download, index); break; 
    223   default: result = NULL; break; 
    224   } 
    225  
    226   if (result == NULL) 
    227     xmlrpc_env_set_fault(env, XMLRPC_TYPE_ERROR, "Invalid index."); 
    228        
    229   return result; 
    230 } 
    231  
    232 // This should really be cleaned up and support for an array of 
    233 // downloads should be added. 
    234 torrent::Object 
    235 xmlrpc_to_object_target(xmlrpc_env* env, xmlrpc_value* value, int callType, void** target) { 
    236   switch (xmlrpc_value_type(value)) { 
    237   case XMLRPC_TYPE_STRING: 
    238     if (callType != XmlRpc::call_download) { 
    239       xmlrpc_env_set_fault(env, XMLRPC_TYPE_ERROR, "Unsupported type found."); 
    240       break; 
    241     } 
    242  
    243     *target = xmlrpc_to_download(env, value); 
    244     break; 
    245  
    246   case XMLRPC_TYPE_ARRAY: 
    247   { 
    248     unsigned int current = 0; 
    249     unsigned int last = xmlrpc_array_size(env, value); 
    250  
    251     if (env->fault_occurred) 
    252       break; 
    253  
    254     if (last < 1) { 
    255       xmlrpc_env_set_fault(env, XMLRPC_TYPE_ERROR, "Too few arguments."); 
    256       break; 
    257     } 
    258  
    259     { 
    260       xmlrpc_value* tmp; 
    261       xmlrpc_array_read_item(env, value, current++, &tmp); 
    262  
    263       if (env->fault_occurred) 
    264         break; 
    265  
    266       *target = xmlrpc_to_download(env, tmp); 
    267       xmlrpc_DECREF(tmp); 
    268  
    269       if (env->fault_occurred) 
    270         break; 
    271     } 
    272  
    273     if (callType == XmlRpc::call_file || callType == XmlRpc::call_tracker) { 
    274       if (current == last) { 
    275         xmlrpc_env_set_fault(env, XMLRPC_TYPE_ERROR, "Too few arguments."); 
    276         break; 
    277       } 
    278  
    279       xmlrpc_value* tmp; 
    280       xmlrpc_array_read_item(env, value, current++, &tmp); 
    281  
    282       if (env->fault_occurred) 
    283         break; 
    284  
    285       *target = xmlrpc_to_index_type(env, tmp, callType, (core::Download*)*target); 
    286       xmlrpc_DECREF(tmp); 
    287  
    288       if (env->fault_occurred) 
    289         break; 
    290     } 
    291  
    292     torrent::Object result; 
    293  
    294     if (current + 1 < last) { 
    295       result = torrent::Object::create_list(); 
    296       torrent::Object::list_type& listRef = result.as_list(); 
    297  
    298       // Move this into a helper function? 
    299       while (current != last) { 
    300         xmlrpc_value* tmp; 
    301         xmlrpc_array_read_item(env, value, current++, &tmp); 
    302  
    303         if (env->fault_occurred) 
    304           break; 
    305  
    306         listRef.push_back(xmlrpc_to_object(env, tmp)); 
    307         xmlrpc_DECREF(tmp); 
    308       } 
    309  
    310       return result; 
    311  
    312     } else if (current + 1 == last) { 
    313       // Need to decref. 
    314       xmlrpc_value* tmp; 
    315       xmlrpc_array_read_item(env, value, current, &tmp); 
    316  
    317       if (env->fault_occurred) 
    318         break; 
    319  
    320       result = xmlrpc_to_object(env, tmp); 
    321       xmlrpc_DECREF(tmp); 
    322     } 
    323  
    324     return result; 
    325   } 
    326  
    327   default: 
    328     xmlrpc_env_set_fault(env, XMLRPC_TYPE_ERROR, "Unsupported type found."); 
    329   } 
    330  
    331   return torrent::Object(); 
     303    throw xmlrpc_error(XMLRPC_TYPE_ERROR, "Unsupported type found."); 
     304  } 
    332305} 
    333306 
     
    381354  } 
    382355 
    383   int   type = itr->second.target(); 
    384   void* target = NULL; 
    385   torrent::Object object = (type == 0) ? xmlrpc_to_object(env, args) : xmlrpc_to_object_target(env, args, type, &target); 
    386  
    387   if (env->fault_occurred) 
     356  try { 
     357    torrent::Object object; 
     358    rpc::target_type target = rpc::make_target(); 
     359 
     360    xmlrpc_to_object(env, args, itr->second.target(), &target).swap(object); 
     361 
     362    if (env->fault_occurred) 
     363      return NULL; 
     364 
     365    return object_to_xmlrpc(env, rpc::commands.call_command(itr, object, target)); 
     366 
     367  } catch (xmlrpc_error& e) { 
     368    xmlrpc_env_set_fault(env, e.type(), e.what()); 
    388369    return NULL; 
    389  
    390   try { 
    391     return object_to_xmlrpc(env, rpc::commands.call_command(itr, object, rpc::make_target(type, target))); 
    392370 
    393371  } catch (torrent::local_error& e) {