Changeset 14079


Ignore:
Timestamp:
May 23, 2013, 12:11:09 AM (9 years ago)
Author:
jordan
Message:

whitespace/indentation

Location:
trunk/libtransmission
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/rpcimpl.c

    r14077 r14079  
    8787struct tr_rpc_idle_data
    8888{
    89     tr_session            * session;
    90     tr_variant            * response;
    91     tr_variant            * args_out;
    92     tr_rpc_response_func    callback;
    93     void                  * callback_user_data;
     89 tr_session            * session;
     90 tr_variant            * response;
     91 tr_variant            * args_out;
     92 tr_rpc_response_func    callback;
     93 void                  * callback_user_data;
    9494};
    9595
     
    9797tr_idle_function_done (struct tr_rpc_idle_data * data, const char * result)
    9898{
    99     struct evbuffer * buf;
    100 
    101     if (result == NULL)
    102         result = "success";
    103     tr_variantDictAddStr (data->response, TR_KEY_result, result);
    104 
    105     buf = tr_variantToBuf (data->response, TR_VARIANT_FMT_JSON_LEAN);
    106   (*data->callback)(data->session, buf, data->callback_user_data);
    107     evbuffer_free (buf);
    108 
    109     tr_variantFree (data->response);
    110     tr_free (data->response);
    111     tr_free (data);
     99 struct evbuffer * buf;
     100
     101 if (result == NULL)
     102   result = "success";
     103 tr_variantDictAddStr (data->response, TR_KEY_result, result);
     104
     105 buf = tr_variantToBuf (data->response, TR_VARIANT_FMT_JSON_LEAN);
     106 (*data->callback)(data->session, buf, data->callback_user_data);
     107 evbuffer_free (buf);
     108
     109 tr_variantFree (data->response);
     110 tr_free (data->response);
     111 tr_free (data);
    112112}
    113113
     
    121121             int        * setmeCount)
    122122{
    123     int           torrentCount = 0;
    124     int64_t       id;
    125     tr_torrent ** torrents = NULL;
    126     tr_variant *     ids;
    127     const char * str;
    128 
    129     if (tr_variantDictFindList (args, TR_KEY_ids, &ids))
    130     {
    131         int       i;
    132         const int n = tr_variantListSize (ids);
    133 
    134         torrents = tr_new0 (tr_torrent *, n);
    135 
    136         for (i = 0; i < n; ++i)
    137         {
    138             tr_torrent * tor = NULL;
    139             tr_variant *    node = tr_variantListChild (ids, i);
    140             const char * str;
    141             if (tr_variantGetInt (node, &id))
    142                 tor = tr_torrentFindFromId (session, id);
    143             else if (tr_variantGetStr (node, &str, NULL))
    144                 tor = tr_torrentFindFromHashString (session, str);
    145             if (tor)
    146                 torrents[torrentCount++] = tor;
    147         }
    148     }
    149     else if (tr_variantDictFindInt (args, TR_KEY_ids, &id)
    150            || tr_variantDictFindInt (args, TR_KEY_id, &id))
    151     {
    152         tr_torrent * tor;
    153         torrents = tr_new0 (tr_torrent *, 1);
    154         if ((tor = tr_torrentFindFromId (session, id)))
     123  int torrentCount = 0;
     124  int64_t id;
     125  tr_torrent ** torrents = NULL;
     126  tr_variant * ids;
     127  const char * str;
     128
     129  if (tr_variantDictFindList (args, TR_KEY_ids, &ids))
     130    {
     131      int i;
     132      const int n = tr_variantListSize (ids);
     133
     134      torrents = tr_new0 (tr_torrent *, n);
     135
     136      for (i=0; i<n; ++i)
     137        {
     138          const char * str;
     139          tr_torrent * tor;
     140          tr_variant * node = tr_variantListChild (ids, i);
     141
     142          if (tr_variantGetInt (node, &id))
     143            tor = tr_torrentFindFromId (session, id);
     144          else if (tr_variantGetStr (node, &str, NULL))
     145            tor = tr_torrentFindFromHashString (session, str);
     146          else
     147            tor = NULL;
     148
     149          if (tor != NULL)
    155150            torrents[torrentCount++] = tor;
    156     }
    157     else if (tr_variantDictFindStr (args, TR_KEY_ids, &str, NULL))
    158     {
    159         if (!strcmp (str, "recently-active"))
    160         {
    161             tr_torrent * tor = NULL;
    162             const time_t now = tr_time ();
    163             const time_t window = RECENTLY_ACTIVE_SECONDS;
    164             const int n = tr_sessionCountTorrents (session);
    165             torrents = tr_new0 (tr_torrent *, n);
    166             while ((tor = tr_torrentNext (session, tor)))
    167                 if (tor->anyDate >= now - window)
    168                     torrents[torrentCount++] = tor;
    169         }
    170         else
    171         {
    172             tr_torrent * tor;
    173             torrents = tr_new0 (tr_torrent *, 1);
    174             if ((tor = tr_torrentFindFromHashString (session, str)))
    175                 torrents[torrentCount++] = tor;
    176         }
    177     }
    178     else /* all of them */
    179     {
    180         tr_torrent * tor = NULL;
    181         const int n = tr_sessionCountTorrents (session);
    182         torrents = tr_new0 (tr_torrent *, n);
    183         while ((tor = tr_torrentNext (session, tor)))
     151        }
     152    }
     153  else if (tr_variantDictFindInt (args, TR_KEY_ids, &id)
     154        || tr_variantDictFindInt (args, TR_KEY_id, &id))
     155    {
     156      tr_torrent * tor;
     157      torrents = tr_new0 (tr_torrent *, 1);
     158      if ((tor = tr_torrentFindFromId (session, id)))
     159        torrents[torrentCount++] = tor;
     160    }
     161  else if (tr_variantDictFindStr (args, TR_KEY_ids, &str, NULL))
     162    {
     163      if (!strcmp (str, "recently-active"))
     164        {
     165          tr_torrent * tor = NULL;
     166          const time_t now = tr_time ();
     167          const time_t window = RECENTLY_ACTIVE_SECONDS;
     168          const int n = tr_sessionCountTorrents (session);
     169          torrents = tr_new0 (tr_torrent *, n);
     170          while ((tor = tr_torrentNext (session, tor)))
     171            if (tor->anyDate >= now - window)
     172              torrents[torrentCount++] = tor;
     173        }
     174      else
     175        {
     176          tr_torrent * tor;
     177          torrents = tr_new0 (tr_torrent *, 1);
     178          if ((tor = tr_torrentFindFromHashString (session, str)))
    184179            torrents[torrentCount++] = tor;
    185     }
    186 
    187     *setmeCount = torrentCount;
    188     return torrents;
     180        }
     181    }
     182  else /* all of them */
     183    {
     184      tr_torrent * tor = NULL;
     185      const int n = tr_sessionCountTorrents (session);
     186      torrents = tr_new0 (tr_torrent *, n);
     187      while ((tor = tr_torrentNext (session, tor)))
     188        torrents[torrentCount++] = tor;
     189    }
     190
     191  *setmeCount = torrentCount;
     192  return torrents;
    189193}
    190194
     
    192196notifyBatchQueueChange (tr_session * session, tr_torrent ** torrents, int n)
    193197{
    194     int i;
    195     for (i=0; i<n; ++i)
    196         notify (session, TR_RPC_TORRENT_CHANGED, torrents[i]);
    197     notify (session, TR_RPC_SESSION_QUEUE_POSITIONS_CHANGED, NULL);
     198  int i;
     199  for (i=0; i<n; ++i)
     200    notify (session, TR_RPC_TORRENT_CHANGED, torrents[i]);
     201  notify (session, TR_RPC_SESSION_QUEUE_POSITIONS_CHANGED, NULL);
    198202}
    199203
     
    204208              struct tr_rpc_idle_data  * idle_data UNUSED)
    205209{
    206     int n;
    207     tr_torrent ** torrents = getTorrents (session, args_in, &n);
    208     tr_torrentsQueueMoveTop (torrents, n);
    209     notifyBatchQueueChange (session, torrents, n);
    210     tr_free (torrents);
    211     return NULL;
     210  int n;
     211  tr_torrent ** torrents = getTorrents (session, args_in, &n);
     212  tr_torrentsQueueMoveTop (torrents, n);
     213  notifyBatchQueueChange (session, torrents, n);
     214  tr_free (torrents);
     215  return NULL;
    212216}
    213217
     
    218222             struct tr_rpc_idle_data  * idle_data UNUSED)
    219223{
    220     int n;
    221     tr_torrent ** torrents = getTorrents (session, args_in, &n);
    222     tr_torrentsQueueMoveUp (torrents, n);
    223     notifyBatchQueueChange (session, torrents, n);
    224     tr_free (torrents);
    225     return NULL;
     224  int n;
     225  tr_torrent ** torrents = getTorrents (session, args_in, &n);
     226  tr_torrentsQueueMoveUp (torrents, n);
     227  notifyBatchQueueChange (session, torrents, n);
     228  tr_free (torrents);
     229  return NULL;
    226230}
    227231
     
    232236               struct tr_rpc_idle_data  * idle_data UNUSED)
    233237{
    234     int n;
    235     tr_torrent ** torrents = getTorrents (session, args_in, &n);
    236     tr_torrentsQueueMoveDown (torrents, n);
    237     notifyBatchQueueChange (session, torrents, n);
    238     tr_free (torrents);
    239     return NULL;
     238  int n;
     239  tr_torrent ** torrents = getTorrents (session, args_in, &n);
     240  tr_torrentsQueueMoveDown (torrents, n);
     241  notifyBatchQueueChange (session, torrents, n);
     242  tr_free (torrents);
     243  return NULL;
    240244}
    241245
     
    246250                 struct tr_rpc_idle_data  * idle_data UNUSED)
    247251{
    248     int n;
    249     tr_torrent ** torrents = getTorrents (session, args_in, &n);
    250     tr_torrentsQueueMoveBottom (torrents, n);
    251     notifyBatchQueueChange (session, torrents, n);
    252     tr_free (torrents);
    253     return NULL;
     252  int n;
     253  tr_torrent ** torrents = getTorrents (session, args_in, &n);
     254  tr_torrentsQueueMoveBottom (torrents, n);
     255  notifyBatchQueueChange (session, torrents, n);
     256  tr_free (torrents);
     257  return NULL;
    254258}
    255259
     
    260264              struct tr_rpc_idle_data  * idle_data UNUSED)
    261265{
    262     int           i, torrentCount;
    263     tr_torrent ** torrents = getTorrents (session, args_in, &torrentCount);
    264 
    265     assert (idle_data == NULL);
    266 
    267     for (i = 0; i < torrentCount; ++i)
    268     {
    269         tr_torrent * tor = torrents[i];
    270         if (!tor->isRunning)
    271         {
    272             tr_torrentStart (tor);
    273             notify (session, TR_RPC_TORRENT_STARTED, tor);
    274         }
    275     }
    276     tr_free (torrents);
    277     return NULL;
     266  int i;
     267  int torrentCount;
     268  tr_torrent ** torrents;
     269
     270  assert (idle_data == NULL);
     271
     272  torrents = getTorrents (session, args_in, &torrentCount);
     273  for (i=0; i<torrentCount; ++i)
     274    {
     275      tr_torrent * tor = torrents[i];
     276      if (!tor->isRunning)
     277        {
     278          tr_torrentStart (tor);
     279          notify (session, TR_RPC_TORRENT_STARTED, tor);
     280        }
     281    }
     282
     283  tr_free (torrents);
     284  return NULL;
    278285}
    279286
     
    284291                 struct tr_rpc_idle_data  * idle_data UNUSED)
    285292{
    286     int           i, torrentCount;
    287     tr_torrent ** torrents = getTorrents (session, args_in, &torrentCount);
    288 
    289     assert (idle_data == NULL);
    290 
    291     for (i = 0; i < torrentCount; ++i)
    292     {
    293         tr_torrent * tor = torrents[i];
    294         if (!tor->isRunning)
    295         {
    296             tr_torrentStartNow (tor);
    297             notify (session, TR_RPC_TORRENT_STARTED, tor);
    298         }
    299     }
    300     tr_free (torrents);
    301     return NULL;
     293  int i;
     294  int torrentCount;
     295  tr_torrent ** torrents;
     296
     297  assert (idle_data == NULL);
     298
     299  torrents = getTorrents (session, args_in, &torrentCount);
     300  for (i=0; i<torrentCount; ++i)
     301    {
     302      tr_torrent * tor = torrents[i];
     303
     304      if (!tor->isRunning)
     305        {
     306          tr_torrentStartNow (tor);
     307          notify (session, TR_RPC_TORRENT_STARTED, tor);
     308        }
     309    }
     310
     311  tr_free (torrents);
     312  return NULL;
    302313}
    303314
     
    308319             struct tr_rpc_idle_data  * idle_data UNUSED)
    309320{
    310     int           i, torrentCount;
    311     tr_torrent ** torrents = getTorrents (session, args_in, &torrentCount);
    312 
    313     assert (idle_data == NULL);
    314 
    315     for (i = 0; i < torrentCount; ++i)
    316     {
    317         tr_torrent * tor = torrents[i];
    318 
    319         if (tor->isRunning || tr_torrentIsQueued (tor))
    320         {
    321             tor->isStopping = true;
    322             notify (session, TR_RPC_TORRENT_STOPPED, tor);
    323         }
    324     }
    325     tr_free (torrents);
    326     return NULL;
     321  int i;
     322  int torrentCount;
     323  tr_torrent ** torrents;
     324
     325  assert (idle_data == NULL);
     326
     327  torrents = getTorrents (session, args_in, &torrentCount);
     328  for (i=0; i<torrentCount; ++i)
     329    {
     330      tr_torrent * tor = torrents[i];
     331
     332      if (tor->isRunning || tr_torrentIsQueued (tor))
     333        {
     334          tor->isStopping = true;
     335          notify (session, TR_RPC_TORRENT_STOPPED, tor);
     336        }
     337    }
     338
     339  tr_free (torrents);
     340  return NULL;
    327341}
    328342
     
    333347               struct tr_rpc_idle_data  * idle_data UNUSED)
    334348{
    335     int i;
    336     int torrentCount;
    337     tr_rpc_callback_type type;
    338     bool deleteFlag = false;
    339     tr_torrent ** torrents = getTorrents (session, args_in, &torrentCount);
    340 
    341     assert (idle_data == NULL);
    342 
    343     tr_variantDictFindBool (args_in, TR_KEY_delete_local_data, &deleteFlag);
    344     type = deleteFlag ? TR_RPC_TORRENT_TRASHING
    345                       : TR_RPC_TORRENT_REMOVING;
    346 
    347     for (i=0; i<torrentCount; ++i)
    348     {
    349         tr_torrent * tor = torrents[i];
    350         const tr_rpc_callback_status status = notify (session, type, tor);
    351         if (! (status & TR_RPC_NOREMOVE))
    352             tr_torrentRemove (tor, deleteFlag, NULL);
    353     }
    354 
    355     tr_free (torrents);
    356     return NULL;
     349  int i;
     350  int torrentCount;
     351  tr_rpc_callback_type type;
     352  bool deleteFlag = false;
     353  tr_torrent ** torrents;
     354
     355  assert (idle_data == NULL);
     356
     357  tr_variantDictFindBool (args_in, TR_KEY_delete_local_data, &deleteFlag);
     358  type = deleteFlag ? TR_RPC_TORRENT_TRASHING
     359                    : TR_RPC_TORRENT_REMOVING;
     360
     361  torrents = getTorrents (session, args_in, &torrentCount);
     362  for (i=0; i<torrentCount; ++i)
     363    {
     364      tr_torrent * tor = torrents[i];
     365      const tr_rpc_callback_status status = notify (session, type, tor);
     366
     367      if (!(status & TR_RPC_NOREMOVE))
     368        tr_torrentRemove (tor, deleteFlag, NULL);
     369    }
     370
     371  tr_free (torrents);
     372  return NULL;
    357373}
    358374
     
    363379                   struct tr_rpc_idle_data  * idle_data UNUSED)
    364380{
    365     int i, torrentCount;
    366     tr_torrent ** torrents = getTorrents (session, args_in, &torrentCount);
    367 
    368     assert (idle_data == NULL);
    369 
    370     for (i=0; i<torrentCount; ++i)
    371     {
    372         tr_torrent * tor = torrents[i];
    373         if (tr_torrentCanManualUpdate (tor))
    374         {
    375             tr_torrentManualUpdate (tor);
    376             notify (session, TR_RPC_TORRENT_CHANGED, tor);
    377         }
    378     }
    379 
    380     tr_free (torrents);
    381     return NULL;
     381  int i;
     382  int torrentCount;
     383  tr_torrent ** torrents;
     384
     385  assert (idle_data == NULL);
     386
     387  torrents = getTorrents (session, args_in, &torrentCount);
     388  for (i=0; i<torrentCount; ++i)
     389    {
     390      tr_torrent * tor = torrents[i];
     391
     392      if (tr_torrentCanManualUpdate (tor))
     393        {
     394          tr_torrentManualUpdate (tor);
     395          notify (session, TR_RPC_TORRENT_CHANGED, tor);
     396        }
     397    }
     398
     399  tr_free (torrents);
     400  return NULL;
    382401}
    383402
     
    388407               struct tr_rpc_idle_data  * idle_data UNUSED)
    389408{
    390     int           i, torrentCount;
    391     tr_torrent ** torrents = getTorrents (session, args_in, &torrentCount);
    392 
    393     assert (idle_data == NULL);
    394 
    395     for (i = 0; i < torrentCount; ++i)
    396     {
    397         tr_torrent * tor = torrents[i];
    398         tr_torrentVerify (tor, NULL, NULL);
    399         notify (session, TR_RPC_TORRENT_CHANGED, tor);
    400     }
    401 
    402     tr_free (torrents);
    403     return NULL;
     409  int i;
     410  int torrentCount;
     411  tr_torrent ** torrents;
     412
     413  assert (idle_data == NULL);
     414
     415  torrents = getTorrents (session, args_in, &torrentCount);
     416  for (i=0; i<torrentCount; ++i)
     417    {
     418      tr_torrent * tor = torrents[i];
     419      tr_torrentVerify (tor, NULL, NULL);
     420      notify (session, TR_RPC_TORRENT_CHANGED, tor);
     421    }
     422
     423  tr_free (torrents);
     424  return NULL;
    404425}
    405426
     
    411432addFileStats (const tr_torrent * tor, tr_variant * list)
    412433{
    413     tr_file_index_t i;
    414     tr_file_index_t n;
    415     const tr_info * info = tr_torrentInfo (tor);
    416     tr_file_stat * files = tr_torrentFiles (tor, &n);
    417 
    418     for (i = 0; i < info->fileCount; ++i)
    419     {
    420         const tr_file * file = &info->files[i];
    421         tr_variant * d = tr_variantListAddDict (list, 3);
    422         tr_variantDictAddInt (d, TR_KEY_bytesCompleted, files[i].bytesCompleted);
    423         tr_variantDictAddInt (d, TR_KEY_priority, file->priority);
    424         tr_variantDictAddBool (d, TR_KEY_wanted, !file->dnd);
    425     }
    426 
    427     tr_torrentFilesFree (files, n);
     434  tr_file_index_t i;
     435  tr_file_index_t n;
     436  const tr_info * info = tr_torrentInfo (tor);
     437  tr_file_stat * files = tr_torrentFiles (tor, &n);
     438
     439  for (i=0; i<info->fileCount; ++i)
     440    {
     441      const tr_file * file = &info->files[i];
     442      tr_variant * d = tr_variantListAddDict (list, 3);
     443      tr_variantDictAddInt (d, TR_KEY_bytesCompleted, files[i].bytesCompleted);
     444      tr_variantDictAddInt (d, TR_KEY_priority, file->priority);
     445      tr_variantDictAddBool (d, TR_KEY_wanted, !file->dnd);
     446    }
     447
     448  tr_torrentFilesFree (files, n);
    428449}
    429450
     
    431452addFiles (const tr_torrent * tor, tr_variant * list)
    432453{
    433     tr_file_index_t i;
    434     tr_file_index_t n;
    435     const tr_info * info = tr_torrentInfo (tor);
    436     tr_file_stat *  files = tr_torrentFiles (tor, &n);
    437 
    438     for (i = 0; i < info->fileCount; ++i)
    439     {
    440         const tr_file * file = &info->files[i];
    441         tr_variant *      d = tr_variantListAddDict (list, 3);
    442         tr_variantDictAddInt (d, TR_KEY_bytesCompleted, files[i].bytesCompleted);
    443         tr_variantDictAddInt (d, TR_KEY_length, file->length);
    444         tr_variantDictAddStr (d, TR_KEY_name, file->name);
    445     }
    446 
    447     tr_torrentFilesFree (files, n);
     454  tr_file_index_t i;
     455  tr_file_index_t n;
     456  const tr_info * info = tr_torrentInfo (tor);
     457  tr_file_stat *  files = tr_torrentFiles (tor, &n);
     458
     459  for (i=0; i<info->fileCount; ++i)
     460    {
     461      const tr_file * file = &info->files[i];
     462      tr_variant * d = tr_variantListAddDict (list, 3);
     463      tr_variantDictAddInt (d, TR_KEY_bytesCompleted, files[i].bytesCompleted);
     464      tr_variantDictAddInt (d, TR_KEY_length, file->length);
     465      tr_variantDictAddStr (d, TR_KEY_name, file->name);
     466    }
     467
     468  tr_torrentFilesFree (files, n);
    448469}
    449470
     
    478499addTrackerStats (const tr_tracker_stat * st, int n, tr_variant * list)
    479500{
    480     int i;
    481 
    482     for (i=0; i<n; ++i)
    483     {
    484         const tr_tracker_stat * s = &st[i];
    485         tr_variant * d = tr_variantListAddDict (list, 26);
    486         tr_variantDictAddStr  (d, TR_KEY_announce, s->announce);
    487         tr_variantDictAddInt  (d, TR_KEY_announceState, s->announceState);
    488         tr_variantDictAddInt  (d, TR_KEY_downloadCount, s->downloadCount);
    489         tr_variantDictAddBool (d, TR_KEY_hasAnnounced, s->hasAnnounced);
    490         tr_variantDictAddBool (d, TR_KEY_hasScraped, s->hasScraped);
    491         tr_variantDictAddStr  (d, TR_KEY_host, s->host);
    492         tr_variantDictAddInt  (d, TR_KEY_id, s->id);
    493         tr_variantDictAddBool (d, TR_KEY_isBackup, s->isBackup);
    494         tr_variantDictAddInt  (d, TR_KEY_lastAnnouncePeerCount, s->lastAnnouncePeerCount);
    495         tr_variantDictAddStr  (d, TR_KEY_lastAnnounceResult, s->lastAnnounceResult);
    496         tr_variantDictAddInt  (d, TR_KEY_lastAnnounceStartTime, s->lastAnnounceStartTime);
    497         tr_variantDictAddBool (d, TR_KEY_lastAnnounceSucceeded, s->lastAnnounceSucceeded);
    498         tr_variantDictAddInt  (d, TR_KEY_lastAnnounceTime, s->lastAnnounceTime);
    499         tr_variantDictAddBool (d, TR_KEY_lastAnnounceTimedOut, s->lastAnnounceTimedOut);
    500         tr_variantDictAddStr  (d, TR_KEY_lastScrapeResult, s->lastScrapeResult);
    501         tr_variantDictAddInt  (d, TR_KEY_lastScrapeStartTime, s->lastScrapeStartTime);
    502         tr_variantDictAddBool (d, TR_KEY_lastScrapeSucceeded, s->lastScrapeSucceeded);
    503         tr_variantDictAddInt  (d, TR_KEY_lastScrapeTime, s->lastScrapeTime);
    504         tr_variantDictAddInt  (d, TR_KEY_lastScrapeTimedOut, s->lastScrapeTimedOut);
    505         tr_variantDictAddInt  (d, TR_KEY_leecherCount, s->leecherCount);
    506         tr_variantDictAddInt  (d, TR_KEY_nextAnnounceTime, s->nextAnnounceTime);
    507         tr_variantDictAddInt  (d, TR_KEY_nextScrapeTime, s->nextScrapeTime);
    508         tr_variantDictAddStr  (d, TR_KEY_scrape, s->scrape);
    509         tr_variantDictAddInt  (d, TR_KEY_scrapeState, s->scrapeState);
    510         tr_variantDictAddInt  (d, TR_KEY_seederCount, s->seederCount);
    511         tr_variantDictAddInt  (d, TR_KEY_tier, s->tier);
     501  int i;
     502
     503  for (i=0; i<n; ++i)
     504    {
     505      const tr_tracker_stat * s = &st[i];
     506      tr_variant * d = tr_variantListAddDict (list, 26);
     507      tr_variantDictAddStr  (d, TR_KEY_announce, s->announce);
     508      tr_variantDictAddInt  (d, TR_KEY_announceState, s->announceState);
     509      tr_variantDictAddInt  (d, TR_KEY_downloadCount, s->downloadCount);
     510      tr_variantDictAddBool (d, TR_KEY_hasAnnounced, s->hasAnnounced);
     511      tr_variantDictAddBool (d, TR_KEY_hasScraped, s->hasScraped);
     512      tr_variantDictAddStr  (d, TR_KEY_host, s->host);
     513      tr_variantDictAddInt  (d, TR_KEY_id, s->id);
     514      tr_variantDictAddBool (d, TR_KEY_isBackup, s->isBackup);
     515      tr_variantDictAddInt  (d, TR_KEY_lastAnnouncePeerCount, s->lastAnnouncePeerCount);
     516      tr_variantDictAddStr  (d, TR_KEY_lastAnnounceResult, s->lastAnnounceResult);
     517      tr_variantDictAddInt  (d, TR_KEY_lastAnnounceStartTime, s->lastAnnounceStartTime);
     518      tr_variantDictAddBool (d, TR_KEY_lastAnnounceSucceeded, s->lastAnnounceSucceeded);
     519      tr_variantDictAddInt  (d, TR_KEY_lastAnnounceTime, s->lastAnnounceTime);
     520      tr_variantDictAddBool (d, TR_KEY_lastAnnounceTimedOut, s->lastAnnounceTimedOut);
     521      tr_variantDictAddStr  (d, TR_KEY_lastScrapeResult, s->lastScrapeResult);
     522      tr_variantDictAddInt  (d, TR_KEY_lastScrapeStartTime, s->lastScrapeStartTime);
     523      tr_variantDictAddBool (d, TR_KEY_lastScrapeSucceeded, s->lastScrapeSucceeded);
     524      tr_variantDictAddInt  (d, TR_KEY_lastScrapeTime, s->lastScrapeTime);
     525      tr_variantDictAddInt  (d, TR_KEY_lastScrapeTimedOut, s->lastScrapeTimedOut);
     526      tr_variantDictAddInt  (d, TR_KEY_leecherCount, s->leecherCount);
     527      tr_variantDictAddInt  (d, TR_KEY_nextAnnounceTime, s->nextAnnounceTime);
     528      tr_variantDictAddInt  (d, TR_KEY_nextScrapeTime, s->nextScrapeTime);
     529      tr_variantDictAddStr  (d, TR_KEY_scrape, s->scrape);
     530      tr_variantDictAddInt  (d, TR_KEY_scrapeState, s->scrapeState);
     531      tr_variantDictAddInt  (d, TR_KEY_seederCount, s->seederCount);
     532      tr_variantDictAddInt  (d, TR_KEY_tier, s->tier);
    512533    }
    513534}
     
    524545  for (i=0; i<peerCount; ++i)
    525546    {
    526         tr_variant * d = tr_variantListAddDict (list, 16);
    527         const tr_peer_stat * peer = peers + i;
    528         tr_variantDictAddStr  (d, TR_KEY_address, peer->addr);
    529         tr_variantDictAddStr  (d, TR_KEY_clientName, peer->client);
    530         tr_variantDictAddBool (d, TR_KEY_clientIsChoked, peer->clientIsChoked);
    531         tr_variantDictAddBool (d, TR_KEY_clientIsInterested, peer->clientIsInterested);
    532         tr_variantDictAddStr  (d, TR_KEY_flagStr, peer->flagStr);
    533         tr_variantDictAddBool (d, TR_KEY_isDownloadingFrom, peer->isDownloadingFrom);
    534         tr_variantDictAddBool (d, TR_KEY_isEncrypted, peer->isEncrypted);
    535         tr_variantDictAddBool (d, TR_KEY_isIncoming, peer->isIncoming);
    536         tr_variantDictAddBool (d, TR_KEY_isUploadingTo, peer->isUploadingTo);
    537         tr_variantDictAddBool (d, TR_KEY_isUTP, peer->isUTP);
    538         tr_variantDictAddBool (d, TR_KEY_peerIsChoked, peer->peerIsChoked);
    539         tr_variantDictAddBool (d, TR_KEY_peerIsInterested, peer->peerIsInterested);
    540         tr_variantDictAddInt  (d, TR_KEY_port, peer->port);
    541         tr_variantDictAddReal (d, TR_KEY_progress, peer->progress);
    542         tr_variantDictAddInt  (d, TR_KEY_rateToClient, toSpeedBytes (peer->rateToClient_KBps));
    543         tr_variantDictAddInt  (d, TR_KEY_rateToPeer, toSpeedBytes (peer->rateToPeer_KBps));
    544     }
    545 
    546     tr_torrentPeersFree (peers, peerCount);
     547      tr_variant * d = tr_variantListAddDict (list, 16);
     548      const tr_peer_stat * peer = peers + i;
     549      tr_variantDictAddStr  (d, TR_KEY_address, peer->addr);
     550      tr_variantDictAddStr  (d, TR_KEY_clientName, peer->client);
     551      tr_variantDictAddBool (d, TR_KEY_clientIsChoked, peer->clientIsChoked);
     552      tr_variantDictAddBool (d, TR_KEY_clientIsInterested, peer->clientIsInterested);
     553      tr_variantDictAddStr  (d, TR_KEY_flagStr, peer->flagStr);
     554      tr_variantDictAddBool (d, TR_KEY_isDownloadingFrom, peer->isDownloadingFrom);
     555      tr_variantDictAddBool (d, TR_KEY_isEncrypted, peer->isEncrypted);
     556      tr_variantDictAddBool (d, TR_KEY_isIncoming, peer->isIncoming);
     557      tr_variantDictAddBool (d, TR_KEY_isUploadingTo, peer->isUploadingTo);
     558      tr_variantDictAddBool (d, TR_KEY_isUTP, peer->isUTP);
     559      tr_variantDictAddBool (d, TR_KEY_peerIsChoked, peer->peerIsChoked);
     560      tr_variantDictAddBool (d, TR_KEY_peerIsInterested, peer->peerIsInterested);
     561      tr_variantDictAddInt  (d, TR_KEY_port, peer->port);
     562      tr_variantDictAddReal (d, TR_KEY_progress, peer->progress);
     563      tr_variantDictAddInt  (d, TR_KEY_rateToClient, toSpeedBytes (peer->rateToClient_KBps));
     564      tr_variantDictAddInt  (d, TR_KEY_rateToPeer, toSpeedBytes (peer->rateToPeer_KBps));
     565    }
     566
     567  tr_torrentPeersFree (peers, peerCount);
    547568}
    548569
     
    899920static const char*
    900921torrentGet (tr_session               * session,
    901             tr_variant                  * args_in,
    902             tr_variant                  * args_out,
     922            tr_variant               * args_in,
     923            tr_variant               * args_out,
    903924            struct tr_rpc_idle_data  * idle_data UNUSED)
    904925{
    905     int           i, torrentCount;
    906     tr_torrent ** torrents = getTorrents (session, args_in, &torrentCount);
    907     tr_variant *     list = tr_variantDictAddList (args_out, TR_KEY_torrents, torrentCount);
    908     tr_variant *     fields;
    909     const char *  msg = NULL;
    910     const char *  strVal;
    911 
    912     assert (idle_data == NULL);
    913 
    914     if (tr_variantDictFindStr (args_in, TR_KEY_ids, &strVal, NULL) && !strcmp (strVal, "recently-active")) {
    915         int n = 0;
    916         tr_variant * d;
    917         const time_t now = tr_time ();
    918         const int interval = RECENTLY_ACTIVE_SECONDS;
    919         tr_variant * removed_out = tr_variantDictAddList (args_out, TR_KEY_removed, 0);
    920         while ((d = tr_variantListChild (&session->removedTorrents, n++))) {
    921             int64_t intVal;
    922             if (tr_variantDictFindInt (d, TR_KEY_date, &intVal) && (intVal >= now - interval)) {
    923                 tr_variantDictFindInt (d, TR_KEY_id, &intVal);
    924                 tr_variantListAddInt (removed_out, intVal);
     926  int i;
     927  int torrentCount;
     928  tr_torrent ** torrents = getTorrents (session, args_in, &torrentCount);
     929  tr_variant * list = tr_variantDictAddList (args_out, TR_KEY_torrents, torrentCount);
     930  tr_variant * fields;
     931  const char * strVal;
     932  const char * errmsg = NULL;
     933
     934  assert (idle_data == NULL);
     935
     936  if (tr_variantDictFindStr (args_in, TR_KEY_ids, &strVal, NULL) && !strcmp (strVal, "recently-active"))
     937    {
     938      int n = 0;
     939      tr_variant * d;
     940      const time_t now = tr_time ();
     941      const int interval = RECENTLY_ACTIVE_SECONDS;
     942      tr_variant * removed_out = tr_variantDictAddList (args_out, TR_KEY_removed, 0);
     943      while ((d = tr_variantListChild (&session->removedTorrents, n++)))
     944        {
     945          int64_t intVal;
     946          if (tr_variantDictFindInt (d, TR_KEY_date, &intVal) && (intVal >= now - interval))
     947            {
     948              tr_variantDictFindInt (d, TR_KEY_id, &intVal);
     949              tr_variantListAddInt (removed_out, intVal);
    925950            }
    926951        }
    927952    }
    928953
    929     if (!tr_variantDictFindList (args_in, TR_KEY_fields, &fields))
    930         msg = "no fields specified";
    931     else for (i = 0; i < torrentCount; ++i)
    932         addInfo (torrents[i], tr_variantListAdd (list), fields);
    933 
    934     tr_free (torrents);
    935     return msg;
     954  if (!tr_variantDictFindList (args_in, TR_KEY_fields, &fields))
     955    errmsg = "no fields specified";
     956  else for (i=0; i<torrentCount; ++i)
     957    addInfo (torrents[i], tr_variantListAdd (list), fields);
     958
     959  tr_free (torrents);
     960  return errmsg;
    936961}
    937962
     
    943968setFilePriorities (tr_torrent * tor,
    944969                   int          priority,
    945                    tr_variant *    list)
    946 {
    947     int i;
    948     int64_t tmp;
    949     int fileCount = 0;
    950     const int n = tr_variantListSize (list);
    951     const char * errmsg = NULL;
    952     tr_file_index_t * files = tr_new0 (tr_file_index_t, tor->info.fileCount);
    953 
    954     if (n)
    955     {
    956         for (i = 0; i < n; ++i) {
    957             if (tr_variantGetInt (tr_variantListChild (list, i), &tmp)) {
    958                 if (0 <= tmp && tmp < tor->info.fileCount) {
    959                     files[fileCount++] = tmp;
    960                 } else {
    961                     errmsg = "file index out of range";
    962                 }
     970                   tr_variant * list)
     971{
     972  int i;
     973  int64_t tmp;
     974  int fileCount = 0;
     975  const int n = tr_variantListSize (list);
     976  const char * errmsg = NULL;
     977  tr_file_index_t * files = tr_new0 (tr_file_index_t, tor->info.fileCount);
     978
     979  if (n)
     980    {
     981      for (i=0; i<n; ++i)
     982        {
     983          if (tr_variantGetInt (tr_variantListChild (list, i), &tmp))
     984            {
     985              if (0 <= tmp && tmp < tor->info.fileCount)
     986                files[fileCount++] = tmp;
     987              else
     988                errmsg = "file index out of range";
    963989            }
    964990        }
    965991    }
    966     else /* if empty set, apply to all */
    967     {
    968         tr_file_index_t t;
    969         for (t = 0; t < tor->info.fileCount; ++t)
    970             files[fileCount++] = t;
    971     }
    972 
    973     if (fileCount)
    974         tr_torrentSetFilePriorities (tor, files, fileCount, priority);
    975 
    976     tr_free (files);
    977     return errmsg;
     992  else /* if empty set, apply to all */
     993    {
     994      tr_file_index_t t;
     995      for (t=0; t<tor->info.fileCount; ++t)
     996        files[fileCount++] = t;
     997    }
     998
     999  if (fileCount)
     1000    tr_torrentSetFilePriorities (tor, files, fileCount, priority);
     1001
     1002  tr_free (files);
     1003  return errmsg;
    9781004}
    9791005
     
    9811007setFileDLs (tr_torrent * tor,
    9821008            int          do_download,
    983             tr_variant *    list)
    984 {
    985     int i;
    986     int64_t tmp;
    987     int fileCount = 0;
    988     const int n = tr_variantListSize (list);
    989     const char * errmsg = NULL;
    990     tr_file_index_t * files = tr_new0 (tr_file_index_t, tor->info.fileCount);
    991 
    992     if (n) /* if argument list, process them */
    993     {
    994         for (i = 0; i < n; ++i) {
    995             if (tr_variantGetInt (tr_variantListChild (list, i), &tmp)) {
    996                 if (0 <= tmp && tmp < tor->info.fileCount) {
    997                     files[fileCount++] = tmp;
    998                 } else {
    999                     errmsg = "file index out of range";
    1000                 }
     1009            tr_variant * list)
     1010{
     1011  int i;
     1012  int64_t tmp;
     1013  int fileCount = 0;
     1014  const int n = tr_variantListSize (list);
     1015  const char * errmsg = NULL;
     1016  tr_file_index_t * files = tr_new0 (tr_file_index_t, tor->info.fileCount);
     1017
     1018  if (n) /* if argument list, process them */
     1019    {
     1020      for (i=0; i<n; ++i)
     1021        {
     1022          if (tr_variantGetInt (tr_variantListChild (list, i), &tmp))
     1023            {
     1024              if (0 <= tmp && tmp < tor->info.fileCount)
     1025                files[fileCount++] = tmp;
     1026              else
     1027                errmsg = "file index out of range";
    10011028            }
    10021029        }
    10031030    }
    1004     else /* if empty set, apply to all */
    1005     {
    1006         tr_file_index_t t;
    1007         for (t = 0; t < tor->info.fileCount; ++t)
    1008             files[fileCount++] = t;
    1009     }
    1010 
    1011     if (fileCount)
    1012         tr_torrentSetFileDLs (tor, files, fileCount, do_download);
    1013 
    1014     tr_free (files);
    1015     return errmsg;
     1031  else /* if empty set, apply to all */
     1032    {
     1033      tr_file_index_t t;
     1034
     1035      for (t=0; t<tor->info.fileCount; ++t)
     1036        files[fileCount++] = t;
     1037    }
     1038
     1039  if (fileCount)
     1040      tr_torrentSetFileDLs (tor, files, fileCount, do_download);
     1041
     1042  tr_free (files);
     1043  return errmsg;
    10161044}
    10171045
     
    10191047findAnnounceUrl (const tr_tracker_info * t, int n, const char * url, int * pos)
    10201048{
    1021     int i;
    1022     bool found = false;
    1023 
    1024     for (i=0; i<n; ++i)
    1025     {
    1026         if (!strcmp (t[i].announce, url))
    1027         {
    1028             found = true;
    1029             if (pos) *pos = i;
    1030             break;
    1031         }
    1032     }
    1033 
    1034     return found;
     1049  int i;
     1050  bool found = false;
     1051
     1052  for (i=0; i<n; ++i)
     1053    {
     1054      if (!strcmp (t[i].announce, url))
     1055        {
     1056          found = true;
     1057
     1058          if (pos != NULL)
     1059            *pos = i;
     1060
     1061          break;
     1062        }
     1063    }
     1064
     1065  return found;
    10351066}
    10361067
     
    10381069copyTrackers (tr_tracker_info * tgt, const tr_tracker_info * src, int n)
    10391070{
    1040     int i;
    1041     int maxTier = -1;
    1042 
    1043     for (i=0; i<n; ++i)
    1044     {
    1045         tgt[i].tier = src[i].tier;
    1046         tgt[i].announce = tr_strdup (src[i].announce);
    1047         maxTier = MAX (maxTier, src[i].tier);
    1048     }
    1049 
    1050     return maxTier;
     1071  int i;
     1072  int maxTier = -1;
     1073
     1074  for (i=0; i<n; ++i)
     1075    {
     1076      tgt[i].tier = src[i].tier;
     1077      tgt[i].announce = tr_strdup (src[i].announce);
     1078      maxTier = MAX (maxTier, src[i].tier);
     1079    }
     1080
     1081  return maxTier;
    10511082}
    10521083
     
    10541085freeTrackers (tr_tracker_info * trackers, int n)
    10551086{
    1056     int i;
    1057 
    1058     for (i=0; i<n; ++i)
    1059         tr_free (trackers[i].announce);
    1060 
    1061     tr_free (trackers);
     1087  int i;
     1088
     1089  for (i=0; i<n; ++i)
     1090    tr_free (trackers[i].announce);
     1091
     1092  tr_free (trackers);
    10621093}
    10631094
     
    10651096addTrackerUrls (tr_torrent * tor, tr_variant * urls)
    10661097{
    1067     int i;
    1068     int n;
    1069     int tier;
    1070     tr_variant * val;
    1071     tr_tracker_info * trackers;
    1072     bool changed = false;
    1073     const tr_info * inf = tr_torrentInfo (tor);
    1074     const char * errmsg = NULL;
    1075 
    1076     /* make a working copy of the existing announce list */
    1077     n = inf->trackerCount;
    1078     trackers = tr_new0 (tr_tracker_info, n + tr_variantListSize (urls));
    1079     tier = copyTrackers (trackers, inf->trackers, n);
    1080 
    1081     /* and add the new ones */
    1082     i = 0;
    1083     while ((val = tr_variantListChild (urls, i++)))
    1084     {
    1085         const char * announce = NULL;
    1086 
    1087         if ( tr_variantGetStr (val, &announce, NULL)
    1088             && tr_urlIsValidTracker (announce)
    1089             && !findAnnounceUrl (trackers, n, announce, NULL))
    1090         {
    1091             trackers[n].tier = ++tier; /* add a new tier */
    1092             trackers[n].announce = tr_strdup (announce);
    1093             ++n;
    1094             changed = true;
    1095         }
    1096     }
    1097 
    1098     if (!changed)
    1099         errmsg = "invalid argument";
    1100     else if (!tr_torrentSetAnnounceList (tor, trackers, n))
    1101         errmsg = "error setting announce list";
    1102 
    1103     freeTrackers (trackers, n);
    1104     return errmsg;
     1098  int i;
     1099  int n;
     1100  int tier;
     1101  tr_variant * val;
     1102  tr_tracker_info * trackers;
     1103  bool changed = false;
     1104  const tr_info * inf = tr_torrentInfo (tor);
     1105  const char * errmsg = NULL;
     1106
     1107  /* make a working copy of the existing announce list */
     1108  n = inf->trackerCount;
     1109  trackers = tr_new0 (tr_tracker_info, n + tr_variantListSize (urls));
     1110  tier = copyTrackers (trackers, inf->trackers, n);
     1111
     1112  /* and add the new ones */
     1113  i = 0;
     1114  while ((val = tr_variantListChild (urls, i++)))
     1115    {
     1116      const char * announce = NULL;
     1117
     1118      if ( tr_variantGetStr (val, &announce, NULL)
     1119          && tr_urlIsValidTracker (announce)
     1120          && !findAnnounceUrl (trackers, n, announce, NULL))
     1121        {
     1122          trackers[n].tier = ++tier; /* add a new tier */
     1123          trackers[n].announce = tr_strdup (announce);
     1124          ++n;
     1125          changed = true;
     1126        }
     1127    }
     1128
     1129  if (!changed)
     1130    errmsg = "invalid argument";
     1131  else if (!tr_torrentSetAnnounceList (tor, trackers, n))
     1132    errmsg = "error setting announce list";
     1133
     1134  freeTrackers (trackers, n);
     1135  return errmsg;
    11051136}
    11061137
     
    11081139replaceTrackers (tr_torrent * tor, tr_variant * urls)
    11091140{
    1110     int i;
    1111     tr_variant * pair[2];
    1112     tr_tracker_info * trackers;
    1113     bool changed = false;
    1114     const tr_info * inf = tr_torrentInfo (tor);
    1115     const int n = inf->trackerCount;
    1116     const char * errmsg = NULL;
    1117 
    1118     /* make a working copy of the existing announce list */
    1119     trackers = tr_new0 (tr_tracker_info, n);
    1120     copyTrackers (trackers, inf->trackers, n);
    1121 
    1122     /* make the substitutions... */
    1123     i = 0;
    1124     while (((pair[0] = tr_variantListChild (urls,i))) &&
    1125         ((pair[1] = tr_variantListChild (urls,i+1))))
    1126     {
    1127         size_t len;
    1128         int64_t pos;
    1129         const char * newval;
    1130 
    1131         if ( tr_variantGetInt (pair[0], &pos)
    1132             && tr_variantGetStr (pair[1], &newval, &len)
    1133             && tr_urlIsValidTracker (newval)
    1134             && pos < n
    1135             && pos >= 0)
    1136         {
    1137             tr_free (trackers[pos].announce);
    1138             trackers[pos].announce = tr_strndup (newval, len);
    1139             changed = true;
    1140         }
    1141 
    1142         i += 2;
    1143     }
    1144 
    1145     if (!changed)
    1146         errmsg = "invalid argument";
    1147     else if (!tr_torrentSetAnnounceList (tor, trackers, n))
    1148         errmsg = "error setting announce list";
    1149 
    1150     freeTrackers (trackers, n);
    1151     return errmsg;
     1141  int i;
     1142  tr_variant * pair[2];
     1143  tr_tracker_info * trackers;
     1144  bool changed = false;
     1145  const tr_info * inf = tr_torrentInfo (tor);
     1146  const int n = inf->trackerCount;
     1147  const char * errmsg = NULL;
     1148
     1149  /* make a working copy of the existing announce list */
     1150  trackers = tr_new0 (tr_tracker_info, n);
     1151  copyTrackers (trackers, inf->trackers, n);
     1152
     1153  /* make the substitutions... */
     1154  i = 0;
     1155  while (((pair[0] = tr_variantListChild (urls,i))) &&
     1156         ((pair[1] = tr_variantListChild (urls,i+1))))
     1157    {
     1158      size_t len;
     1159      int64_t pos;
     1160      const char * newval;
     1161
     1162      if (tr_variantGetInt (pair[0], &pos)
     1163          && tr_variantGetStr (pair[1], &newval, &len)
     1164          && tr_urlIsValidTracker (newval)
     1165          && pos < n
     1166          && pos >= 0)
     1167        {
     1168          tr_free (trackers[pos].announce);
     1169          trackers[pos].announce = tr_strndup (newval, len);
     1170          changed = true;
     1171        }
     1172
     1173      i += 2;
     1174    }
     1175
     1176  if (!changed)
     1177    errmsg = "invalid argument";
     1178  else if (!tr_torrentSetAnnounceList (tor, trackers, n))
     1179    errmsg = "error setting announce list";
     1180
     1181  freeTrackers (trackers, n);
     1182  return errmsg;
    11521183}
    11531184
     
    11551186removeTrackers (tr_torrent * tor, tr_variant * ids)
    11561187{
    1157     int i;
    1158     int n;
    1159     int t = 0;
    1160     int dup = -1;
    1161     int * tids;
    1162     tr_variant * val;
    1163     tr_tracker_info * trackers;
    1164     bool changed = false;
    1165     const tr_info * inf = tr_torrentInfo (tor);
    1166     const char * errmsg = NULL;
    1167 
    1168     /* make a working copy of the existing announce list */
    1169     n = inf->trackerCount;
    1170     tids = tr_new0 (int, n);
    1171     trackers = tr_new0 (tr_tracker_info, n);
    1172     copyTrackers (trackers, inf->trackers, n);
    1173 
    1174     /* remove the ones specified in the urls list */
    1175     i = 0;
    1176     while ((val = tr_variantListChild (ids, i++)))
    1177     {
    1178         int64_t pos;
    1179 
    1180         if ( tr_variantGetInt (val, &pos)
    1181             && pos < n
    1182             && pos >= 0)
    1183             tids[t++] = pos;
    1184     }
    1185 
    1186     /* sort trackerIds and remove from largest to smallest so there is no need to recacluate array indicies */
    1187     qsort (tids, t, sizeof (int), compareInt);
    1188     while (t--)
    1189     {
    1190         /* check for duplicates */
    1191         if (tids[t] == dup)
    1192             continue;
    1193         tr_removeElementFromArray (trackers, tids[t], sizeof (tr_tracker_info), n--);
    1194         dup = tids[t];
    1195         changed = true;
    1196     }
    1197 
    1198     if (!changed)
    1199         errmsg = "invalid argument";
    1200     else if (!tr_torrentSetAnnounceList (tor, trackers, n))
    1201         errmsg = "error setting announce list";
    1202 
    1203     freeTrackers (trackers, n);
    1204     tr_free (tids);
    1205     return errmsg;
     1188  int i;
     1189  int n;
     1190  int t = 0;
     1191  int dup = -1;
     1192  int * tids;
     1193  tr_variant * val;
     1194  tr_tracker_info * trackers;
     1195  bool changed = false;
     1196  const tr_info * inf = tr_torrentInfo (tor);
     1197  const char * errmsg = NULL;
     1198
     1199  /* make a working copy of the existing announce list */
     1200  n = inf->trackerCount;
     1201  tids = tr_new0 (int, n);
     1202  trackers = tr_new0 (tr_tracker_info, n);
     1203  copyTrackers (trackers, inf->trackers, n);
     1204
     1205  /* remove the ones specified in the urls list */
     1206  i = 0;
     1207  while ((val = tr_variantListChild (ids, i++)))
     1208    {
     1209      int64_t pos;
     1210
     1211      if (tr_variantGetInt (val, &pos) && (0 <= pos) && (pos < n))
     1212        tids[t++] = pos;
     1213    }
     1214
     1215  /* sort trackerIds and remove from largest to smallest so there is no need to recacluate array indicies */
     1216  qsort (tids, t, sizeof (int), compareInt);
     1217  while (t--)
     1218    {
     1219      /* check for duplicates */
     1220      if (tids[t] == dup)
     1221        continue;
     1222      tr_removeElementFromArray (trackers, tids[t], sizeof (tr_tracker_info), n--);
     1223      dup = tids[t];
     1224      changed = true;
     1225    }
     1226
     1227  if (!changed)
     1228    errmsg = "invalid argument";
     1229  else if (!tr_torrentSetAnnounceList (tor, trackers, n))
     1230    errmsg = "error setting announce list";
     1231
     1232  freeTrackers (trackers, n);
     1233  tr_free (tids);
     1234  return errmsg;
    12061235}
    12071236
     
    12121241            struct tr_rpc_idle_data  * idle_data UNUSED)
    12131242{
    1214     const char * errmsg = NULL;
    1215     int i, torrentCount;
    1216     tr_torrent ** torrents = getTorrents (session, args_in, &torrentCount);
    1217 
    1218     assert (idle_data == NULL);
    1219 
    1220     for (i = 0; i < torrentCount; ++i)
    1221     {
    1222         int64_t      tmp;
    1223         double       d;
    1224         tr_variant *    files;
    1225         tr_variant *    trackers;
    1226         bool         boolVal;
    1227         tr_torrent * tor = torrents[i];
    1228 
    1229         if (tr_variantDictFindInt (args_in, TR_KEY_bandwidthPriority, &tmp))
    1230             if (tr_isPriority (tmp))
    1231                 tr_torrentSetPriority (tor, tmp);
    1232         if (!errmsg && tr_variantDictFindList (args_in, TR_KEY_files_unwanted, &files))
    1233             errmsg = setFileDLs (tor, false, files);
    1234         if (!errmsg && tr_variantDictFindList (args_in, TR_KEY_files_wanted, &files))
    1235             errmsg = setFileDLs (tor, true, files);
    1236         if (tr_variantDictFindInt (args_in, TR_KEY_peer_limit, &tmp))
    1237             tr_torrentSetPeerLimit (tor, tmp);
    1238         if (!errmsg &&  tr_variantDictFindList (args_in, TR_KEY_priority_high, &files))
    1239             errmsg = setFilePriorities (tor, TR_PRI_HIGH, files);
    1240         if (!errmsg && tr_variantDictFindList (args_in, TR_KEY_priority_low, &files))
    1241             errmsg = setFilePriorities (tor, TR_PRI_LOW, files);
    1242         if (!errmsg && tr_variantDictFindList (args_in, TR_KEY_priority_normal, &files))
    1243             errmsg = setFilePriorities (tor, TR_PRI_NORMAL, files);
    1244         if (tr_variantDictFindInt (args_in, TR_KEY_downloadLimit, &tmp))
    1245             tr_torrentSetSpeedLimit_KBps (tor, TR_DOWN, tmp);
    1246         if (tr_variantDictFindBool (args_in, TR_KEY_downloadLimited, &boolVal))
    1247             tr_torrentUseSpeedLimit (tor, TR_DOWN, boolVal);
    1248         if (tr_variantDictFindBool (args_in, TR_KEY_honorsSessionLimits, &boolVal))
    1249             tr_torrentUseSessionLimits (tor, boolVal);
    1250         if (tr_variantDictFindInt (args_in, TR_KEY_uploadLimit, &tmp))
    1251             tr_torrentSetSpeedLimit_KBps (tor, TR_UP, tmp);
    1252         if (tr_variantDictFindBool (args_in, TR_KEY_uploadLimited, &boolVal))
    1253             tr_torrentUseSpeedLimit (tor, TR_UP, boolVal);
    1254         if (tr_variantDictFindInt (args_in, TR_KEY_seedIdleLimit, &tmp))
    1255             tr_torrentSetIdleLimit (tor, tmp);
    1256         if (tr_variantDictFindInt (args_in, TR_KEY_seedIdleMode, &tmp))
    1257             tr_torrentSetIdleMode (tor, tmp);
    1258         if (tr_variantDictFindReal (args_in, TR_KEY_seedRatioLimit, &d))
    1259             tr_torrentSetRatioLimit (tor, d);
    1260         if (tr_variantDictFindInt (args_in, TR_KEY_seedRatioMode, &tmp))
    1261             tr_torrentSetRatioMode (tor, tmp);
    1262         if (tr_variantDictFindInt (args_in, TR_KEY_queuePosition, &tmp))
    1263             tr_torrentSetQueuePosition (tor, tmp);
    1264         if (!errmsg && tr_variantDictFindList (args_in, TR_KEY_trackerAdd, &trackers))
    1265             errmsg = addTrackerUrls (tor, trackers);
    1266         if (!errmsg && tr_variantDictFindList (args_in, TR_KEY_trackerRemove, &trackers))
    1267             errmsg = removeTrackers (tor, trackers);
    1268         if (!errmsg && tr_variantDictFindList (args_in, TR_KEY_trackerReplace, &trackers))
    1269             errmsg = replaceTrackers (tor, trackers);
    1270         notify (session, TR_RPC_TORRENT_CHANGED, tor);
    1271     }
    1272 
    1273     tr_free (torrents);
    1274     return errmsg;
     1243  int i;
     1244  int torrentCount;
     1245  tr_torrent ** torrents;
     1246  const char * errmsg = NULL;
     1247
     1248  assert (idle_data == NULL);
     1249
     1250  torrents = getTorrents (session, args_in, &torrentCount);
     1251
     1252  for (i=0; i<torrentCount; ++i)
     1253    {
     1254      int64_t tmp;
     1255      double d;
     1256      tr_variant * files;
     1257      tr_variant * trackers;
     1258      bool boolVal;
     1259      tr_torrent * tor;
     1260
     1261      tor = torrents[i];
     1262
     1263      if (tr_variantDictFindInt (args_in, TR_KEY_bandwidthPriority, &tmp))
     1264        if (tr_isPriority (tmp))
     1265          tr_torrentSetPriority (tor, tmp);
     1266
     1267      if (!errmsg && tr_variantDictFindList (args_in, TR_KEY_files_unwanted, &files))
     1268        errmsg = setFileDLs (tor, false, files);
     1269
     1270      if (!errmsg && tr_variantDictFindList (args_in, TR_KEY_files_wanted, &files))
     1271        errmsg = setFileDLs (tor, true, files);
     1272
     1273      if (tr_variantDictFindInt (args_in, TR_KEY_peer_limit, &tmp))
     1274        tr_torrentSetPeerLimit (tor, tmp);
     1275
     1276      if (!errmsg &&  tr_variantDictFindList (args_in, TR_KEY_priority_high, &files))
     1277        errmsg = setFilePriorities (tor, TR_PRI_HIGH, files);
     1278
     1279      if (!errmsg && tr_variantDictFindList (args_in, TR_KEY_priority_low, &files))
     1280        errmsg = setFilePriorities (tor, TR_PRI_LOW, files);
     1281
     1282      if (!errmsg && tr_variantDictFindList (args_in, TR_KEY_priority_normal, &files))
     1283        errmsg = setFilePriorities (tor, TR_PRI_NORMAL, files);
     1284
     1285      if (tr_variantDictFindInt (args_in, TR_KEY_downloadLimit, &tmp))
     1286        tr_torrentSetSpeedLimit_KBps (tor, TR_DOWN, tmp);
     1287
     1288      if (tr_variantDictFindBool (args_in, TR_KEY_downloadLimited, &boolVal))
     1289        tr_torrentUseSpeedLimit (tor, TR_DOWN, boolVal);
     1290
     1291      if (tr_variantDictFindBool (args_in, TR_KEY_honorsSessionLimits, &boolVal))
     1292        tr_torrentUseSessionLimits (tor, boolVal);
     1293
     1294      if (tr_variantDictFindInt (args_in, TR_KEY_uploadLimit, &tmp))
     1295        tr_torrentSetSpeedLimit_KBps (tor, TR_UP, tmp);
     1296
     1297      if (tr_variantDictFindBool (args_in, TR_KEY_uploadLimited, &boolVal))
     1298        tr_torrentUseSpeedLimit (tor, TR_UP, boolVal);
     1299
     1300      if (tr_variantDictFindInt (args_in, TR_KEY_seedIdleLimit, &tmp))
     1301        tr_torrentSetIdleLimit (tor, tmp);
     1302
     1303      if (tr_variantDictFindInt (args_in, TR_KEY_seedIdleMode, &tmp))
     1304        tr_torrentSetIdleMode (tor, tmp);
     1305
     1306      if (tr_variantDictFindReal (args_in, TR_KEY_seedRatioLimit, &d))
     1307        tr_torrentSetRatioLimit (tor, d);
     1308
     1309      if (tr_variantDictFindInt (args_in, TR_KEY_seedRatioMode, &tmp))
     1310        tr_torrentSetRatioMode (tor, tmp);
     1311
     1312      if (tr_variantDictFindInt (args_in, TR_KEY_queuePosition, &tmp))
     1313        tr_torrentSetQueuePosition (tor, tmp);
     1314
     1315      if (!errmsg && tr_variantDictFindList (args_in, TR_KEY_trackerAdd, &trackers))
     1316        errmsg = addTrackerUrls (tor, trackers);
     1317
     1318      if (!errmsg && tr_variantDictFindList (args_in, TR_KEY_trackerRemove, &trackers))
     1319        errmsg = removeTrackers (tor, trackers);
     1320
     1321      if (!errmsg && tr_variantDictFindList (args_in, TR_KEY_trackerReplace, &trackers))
     1322        errmsg = replaceTrackers (tor, trackers);
     1323
     1324      notify (session, TR_RPC_TORRENT_CHANGED, tor);
     1325    }
     1326
     1327  tr_free (torrents);
     1328  return errmsg;
    12751329}
    12761330
     
    13751429            void             * user_data)
    13761430{
    1377     char result[1024];
    1378     struct tr_rpc_idle_data * data = user_data;
    1379 
    1380     if (response_code != 200)
    1381     {
    1382         tr_snprintf (result, sizeof (result), "portTested: http error %ld: %s",
    1383                      response_code, tr_webGetResponseStr (response_code));
    1384     }
    1385     else /* success */
    1386     {
    1387         const bool isOpen = response_byte_count && * (char*)response == '1';
    1388         tr_variantDictAddBool (data->args_out, TR_KEY_port_is_open, isOpen);
    1389         tr_snprintf (result, sizeof (result), "success");
     1431  char result[1024];
     1432  struct tr_rpc_idle_data * data = user_data;
     1433
     1434  if (response_code != 200)
     1435    {
     1436      tr_snprintf (result, sizeof (result), "portTested: http error %ld: %s",
     1437                   response_code, tr_webGetResponseStr (response_code));
     1438    }
     1439  else /* success */
     1440    {
     1441      const bool isOpen = response_byte_count && * (char*)response == '1';
     1442      tr_variantDictAddBool (data->args_out, TR_KEY_port_is_open, isOpen);
     1443      tr_snprintf (result, sizeof (result), "success");
    13901444    }
    13911445
     
    13991453          struct tr_rpc_idle_data  * idle_data)
    14001454{
    1401     const int port = tr_sessionGetPeerPort (session);
    1402     char * url = tr_strdup_printf ("http://portcheck.transmissionbt.com/%d", port);
    1403     tr_webRun (session, url, portTested, idle_data);
    1404     tr_free (url);
    1405     return NULL;
     1455  const int port = tr_sessionGetPeerPort (session);
     1456  char * url = tr_strdup_printf ("http://portcheck.transmissionbt.com/%d", port);
     1457  tr_webRun (session, url, portTested, idle_data);
     1458  tr_free (url);
     1459  return NULL;
    14061460}
    14071461
     
    14191473                 void             * user_data)
    14201474{
    1421     char result[1024];
    1422     struct tr_rpc_idle_data * data = user_data;
    1423 
    1424     *result = '\0';
    1425 
    1426     if (response_code != 200)
    1427     {
    1428         tr_snprintf (result, sizeof (result), "gotNewBlocklist: http error %ld: %s",
    1429                      response_code, tr_webGetResponseStr (response_code));
    1430     }
    1431     else /* successfully fetched the blocklist... */
    1432     {
    1433         int fd;
    1434         int err;
    1435         char * filename;
    1436         z_stream stream;
    1437         const char * configDir = tr_sessionGetConfigDir (session);
    1438         const size_t buflen = 1024 * 128; /* 128 KiB buffer */
    1439         uint8_t * buf = tr_valloc (buflen);
    1440 
    1441         /* this is an odd Magic Number required by zlib to enable gz support.
    1442            See zlib's inflateInit2 () documentation for a full description */
    1443         const int windowBits = 15 + 32;
    1444 
    1445         stream.zalloc = (alloc_func) Z_NULL;
    1446         stream.zfree = (free_func) Z_NULL;
    1447         stream.opaque = (voidpf) Z_NULL;
    1448         stream.next_in = (void*) response;
    1449         stream.avail_in = response_byte_count;
    1450         inflateInit2 (&stream, windowBits);
    1451 
    1452         filename = tr_buildPath (configDir, "blocklist.tmp", NULL);
    1453         fd = tr_open_file_for_writing (filename);
    1454         if (fd < 0)
    1455             tr_snprintf (result, sizeof (result), _("Couldn't save file \"%1$s\": %2$s"), filename, tr_strerror (errno));
    1456 
    1457         for (;;)
    1458         {
    1459             stream.next_out = (void*) buf;
    1460             stream.avail_out = buflen;
    1461             err = inflate (&stream, Z_NO_FLUSH);
    1462 
    1463             if (stream.avail_out < buflen) {
    1464                 const int e = write (fd, buf, buflen - stream.avail_out);
    1465                 if (e < 0) {
    1466                     tr_snprintf (result, sizeof (result), _("Couldn't save file \"%1$s\": %2$s"), filename, tr_strerror (errno));
    1467                     break;
     1475  char result[1024];
     1476  struct tr_rpc_idle_data * data = user_data;
     1477
     1478  *result = '\0';
     1479
     1480  if (response_code != 200)
     1481    {
     1482      tr_snprintf (result, sizeof (result), "gotNewBlocklist: http error %ld: %s",
     1483                   response_code, tr_webGetResponseStr (response_code));
     1484    }
     1485  else /* successfully fetched the blocklist... */
     1486    {
     1487      int fd;
     1488      int err;
     1489      char * filename;
     1490      z_stream stream;
     1491      const char * configDir = tr_sessionGetConfigDir (session);
     1492      const size_t buflen = 1024 * 128; /* 128 KiB buffer */
     1493      uint8_t * buf = tr_valloc (buflen);
     1494
     1495      /* this is an odd Magic Number required by zlib to enable gz support.
     1496         See zlib's inflateInit2 () documentation for a full description */
     1497      const int windowBits = 15 + 32;
     1498
     1499      stream.zalloc = (alloc_func) Z_NULL;
     1500      stream.zfree = (free_func) Z_NULL;
     1501      stream.opaque = (voidpf) Z_NULL;
     1502      stream.next_in = (void*) response;
     1503      stream.avail_in = response_byte_count;
     1504      inflateInit2 (&stream, windowBits);
     1505
     1506      filename = tr_buildPath (configDir, "blocklist.tmp", NULL);
     1507      fd = tr_open_file_for_writing (filename);
     1508      if (fd < 0)
     1509        tr_snprintf (result, sizeof (result), _("Couldn't save file \"%1$s\": %2$s"), filename, tr_strerror (errno));
     1510
     1511      for (;;)
     1512        {
     1513          stream.next_out = (void*) buf;
     1514          stream.avail_out = buflen;
     1515          err = inflate (&stream, Z_NO_FLUSH);
     1516
     1517          if (stream.avail_out < buflen)
     1518            {
     1519              const int e = write (fd, buf, buflen - stream.avail_out);
     1520              if (e < 0)
     1521                {
     1522                  tr_snprintf (result, sizeof (result), _("Couldn't save file \"%1$s\": %2$s"), filename, tr_strerror (errno));
     1523                  break;
    14681524                }
    14691525            }
    14701526
    1471             if (err != Z_OK) {
    1472                 if ((err != Z_STREAM_END) && (err != Z_DATA_ERROR))
    1473                     tr_snprintf (result, sizeof (result), _("Error uncompressing blocklist: %s (%d)"), zError (err), err);
    1474                 break;
     1527          if (err != Z_OK)
     1528            {
     1529              if ((err != Z_STREAM_END) && (err != Z_DATA_ERROR))
     1530                tr_snprintf (result, sizeof (result), _("Error uncompressing blocklist: %s (%d)"), zError (err), err);
     1531              break;
    14751532            }
    14761533        }
    14771534
    1478         inflateEnd (&stream);
    1479 
    1480         if (err == Z_DATA_ERROR) /* couldn't inflate it... it's probably already uncompressed */
    1481             if (write (fd, response, response_byte_count) < 0)
    1482                 tr_snprintf (result, sizeof (result), _("Couldn't save file \"%1$s\": %2$s"), filename, tr_strerror (errno));
    1483 
    1484         if (*result)
    1485             tr_logAddError ("%s", result);
    1486         else {
    1487             /* feed it to the session and give the client a response */
    1488             const int rule_count = tr_blocklistSetContent (session, filename);
    1489             tr_variantDictAddInt (data->args_out, TR_KEY_blocklist_size, rule_count);
    1490             tr_snprintf (result, sizeof (result), "success");
    1491         }
    1492 
    1493         tr_remove (filename);
    1494         tr_free (filename);
    1495         tr_free (buf);
    1496     }
    1497 
    1498     tr_idle_function_done (data, result);
     1535      inflateEnd (&stream);
     1536
     1537      if (err == Z_DATA_ERROR) /* couldn't inflate it... it's probably already uncompressed */
     1538        if (write (fd, response, response_byte_count) < 0)
     1539          tr_snprintf (result, sizeof (result), _("Couldn't save file \"%1$s\": %2$s"), filename, tr_strerror (errno));
     1540
     1541      if (*result)
     1542        {
     1543          tr_logAddError ("%s", result);
     1544        }
     1545      else
     1546        {
     1547          /* feed it to the session and give the client a response */
     1548          const int rule_count = tr_blocklistSetContent (session, filename);
     1549          tr_variantDictAddInt (data->args_out, TR_KEY_blocklist_size, rule_count);
     1550          tr_snprintf (result, sizeof (result), "success");
     1551        }
     1552
     1553      tr_remove (filename);
     1554      tr_free (filename);
     1555      tr_free (buf);
     1556    }
     1557
     1558  tr_idle_function_done (data, result);
    14991559}
    15001560
     
    15051565                 struct tr_rpc_idle_data  * idle_data)
    15061566{
    1507     tr_webRun (session, session->blocklist_url, gotNewBlocklist, idle_data);
    1508     return NULL;
     1567  tr_webRun (session, session->blocklist_url, gotNewBlocklist, idle_data);
     1568  return NULL;
    15091569}
    15101570
     
    15611621struct add_torrent_idle_data
    15621622{
    1563     struct tr_rpc_idle_data * data;
    1564     tr_ctor * ctor;
     1623  struct tr_rpc_idle_data * data;
     1624  tr_ctor * ctor;
    15651625};
    15661626
     
    15741634                    void             * user_data)
    15751635{
    1576     struct add_torrent_idle_data * data = user_data;
    1577 
    1578     dbgmsg ("torrentAdd: HTTP response code was %ld (%s); response length was %zu bytes",
    1579             response_code, tr_webGetResponseStr (response_code), response_byte_count);
    1580 
    1581     if (response_code==200 || response_code==221) /* http or ftp success.. */
    1582     {
    1583         tr_ctorSetMetainfo (data->ctor, response, response_byte_count);
    1584         addTorrentImpl (data->data, data->ctor);
    1585     }
    1586     else
    1587     {
    1588         char result[1024];
    1589         tr_snprintf (result, sizeof (result), "gotMetadataFromURL: http error %ld: %s",
    1590                      response_code, tr_webGetResponseStr (response_code));
    1591         tr_idle_function_done (data->data, result);
    1592     }
    1593 
    1594     tr_free (data);
     1636  struct add_torrent_idle_data * data = user_data;
     1637
     1638  dbgmsg ("torrentAdd: HTTP response code was %ld (%s); response length was %zu bytes",
     1639          response_code, tr_webGetResponseStr (response_code), response_byte_count);
     1640
     1641  if (response_code==200 || response_code==221) /* http or ftp success.. */
     1642    {
     1643      tr_ctorSetMetainfo (data->ctor, response, response_byte_count);
     1644      addTorrentImpl (data->data, data->ctor);
     1645    }
     1646  else
     1647    {
     1648      char result[1024];
     1649      tr_snprintf (result, sizeof (result), "gotMetadataFromURL: http error %ld: %s",
     1650                   response_code, tr_webGetResponseStr (response_code));
     1651      tr_idle_function_done (data->data, result);
     1652    }
     1653
     1654  tr_free (data);
    15951655}
    15961656
     
    15981658isCurlURL (const char * filename)
    15991659{
    1600     if (filename == NULL)
    1601         return false;
    1602 
    1603     return !strncmp (filename, "ftp://", 6) ||
    1604            !strncmp (filename, "http://", 7) ||
    1605            !strncmp (filename, "https://", 8);
     1660  if (filename == NULL)
     1661    return false;
     1662
     1663  return !strncmp (filename, "ftp://", 6) ||
     1664         !strncmp (filename, "http://", 7) ||
     1665         !strncmp (filename, "https://", 8);
    16061666}
    16071667
     
    16091669fileListFromList (tr_variant * list, tr_file_index_t * setmeCount)
    16101670{
    1611     size_t i;
    1612     const size_t childCount = tr_variantListSize (list);
    1613     tr_file_index_t n = 0;
    1614     tr_file_index_t * files = tr_new0 (tr_file_index_t, childCount);
    1615 
    1616     for (i=0; i<childCount; ++i) {
    1617         int64_t intVal;
    1618         if (tr_variantGetInt (tr_variantListChild (list, i), &intVal))
    1619             files[n++] = (tr_file_index_t)intVal;
    1620     }
    1621 
    1622     *setmeCount = n;
    1623     return files;
     1671  size_t i;
     1672  const size_t childCount = tr_variantListSize (list);
     1673  tr_file_index_t n = 0;
     1674  tr_file_index_t * files = tr_new0 (tr_file_index_t, childCount);
     1675
     1676  for (i=0; i<childCount; ++i)
     1677    {
     1678      int64_t intVal;
     1679      if (tr_variantGetInt (tr_variantListChild (list, i), &intVal))
     1680        files[n++] = (tr_file_index_t)intVal;
     1681    }
     1682
     1683  *setmeCount = n;
     1684  return files;
    16241685}
    16251686
     
    16301691            struct tr_rpc_idle_data  * idle_data)
    16311692{
    1632     const char * filename = NULL;
    1633     const char * metainfo_base64 = NULL;
    1634 
    1635     assert (idle_data != NULL);
    1636 
    1637     tr_variantDictFindStr (args_in, TR_KEY_filename, &filename, NULL);
    1638     tr_variantDictFindStr (args_in, TR_KEY_metainfo, &metainfo_base64, NULL);
    1639     if (!filename && !metainfo_base64)
    1640         return "no filename or metainfo specified";
    1641     else
    1642     {
    1643         int64_t      i;
    1644         bool         boolVal;
    1645         tr_variant    * l;
    1646         const char * str;
    1647         const char * cookies = NULL;
    1648         tr_ctor    * ctor = tr_ctorNew (session);
    1649 
    1650         /* set the optional arguments */
    1651 
    1652         tr_variantDictFindStr (args_in, TR_KEY_cookies, &cookies, NULL);
    1653 
    1654         if (tr_variantDictFindStr (args_in, TR_KEY_download_dir, &str, NULL))
    1655             tr_ctorSetDownloadDir (ctor, TR_FORCE, str);
    1656 
    1657         if (tr_variantDictFindBool (args_in, TR_KEY_paused, &boolVal))
    1658             tr_ctorSetPaused (ctor, TR_FORCE, boolVal);
    1659 
    1660         if (tr_variantDictFindInt (args_in, TR_KEY_peer_limit, &i))
    1661             tr_ctorSetPeerLimit (ctor, TR_FORCE, i);
    1662 
    1663         if (tr_variantDictFindInt (args_in, TR_KEY_bandwidthPriority, &i))
    1664             tr_ctorSetBandwidthPriority (ctor, i);
    1665 
    1666         if (tr_variantDictFindList (args_in, TR_KEY_files_unwanted, &l)) {
    1667             tr_file_index_t fileCount;
    1668             tr_file_index_t * files = fileListFromList (l, &fileCount);
    1669             tr_ctorSetFilesWanted (ctor, files, fileCount, false);
    1670             tr_free (files);
    1671         }
    1672         if (tr_variantDictFindList (args_in, TR_KEY_files_wanted, &l)) {
    1673             tr_file_index_t fileCount;
    1674             tr_file_index_t * files = fileListFromList (l, &fileCount);
    1675             tr_ctorSetFilesWanted (ctor, files, fileCount, true);
    1676             tr_free (files);
    1677         }
    1678 
    1679         if (tr_variantDictFindList (args_in, TR_KEY_priority_low, &l)) {
    1680             tr_file_index_t fileCount;
    1681             tr_file_index_t * files = fileListFromList (l, &fileCount);
    1682             tr_ctorSetFilePriorities (ctor, files, fileCount, TR_PRI_LOW);
    1683             tr_free (files);
    1684         }
    1685         if (tr_variantDictFindList (args_in, TR_KEY_priority_normal, &l)) {
    1686             tr_file_index_t fileCount;
    1687             tr_file_index_t * files = fileListFromList (l, &fileCount);
    1688             tr_ctorSetFilePriorities (ctor, files, fileCount, TR_PRI_NORMAL);
    1689             tr_free (files);
    1690         }
    1691         if (tr_variantDictFindList (args_in, TR_KEY_priority_high, &l)) {
    1692             tr_file_index_t fileCount;
    1693             tr_file_index_t * files = fileListFromList (l, &fileCount);
    1694             tr_ctorSetFilePriorities (ctor, files, fileCount, TR_PRI_HIGH);
    1695             tr_free (files);
    1696         }
    1697 
    1698         dbgmsg ("torrentAdd: filename is \"%s\"", filename ? filename : " (null)");
    1699 
    1700         if (isCurlURL (filename))
    1701         {
    1702             struct add_torrent_idle_data * d = tr_new0 (struct add_torrent_idle_data, 1);
    1703             d->data = idle_data;
    1704             d->ctor = ctor;
    1705             tr_webRunWithCookies (session, filename, cookies, gotMetadataFromURL, d);
    1706         }
    1707         else
    1708         {
    1709             char * fname = tr_strstrip (tr_strdup (filename));
    1710 
    1711             if (fname == NULL)
     1693  const char * filename = NULL;
     1694  const char * metainfo_base64 = NULL;
     1695
     1696  assert (idle_data != NULL);
     1697
     1698  tr_variantDictFindStr (args_in, TR_KEY_filename, &filename, NULL);
     1699  tr_variantDictFindStr (args_in, TR_KEY_metainfo, &metainfo_base64, NULL);
     1700  if (!filename && !metainfo_base64)
     1701    {
     1702      return "no filename or metainfo specified";
     1703    }
     1704  else
     1705    {
     1706      int64_t i;
     1707      bool boolVal;
     1708      tr_variant * l;
     1709      const char * str;
     1710      const char * cookies = NULL;
     1711      tr_ctor * ctor = tr_ctorNew (session);
     1712
     1713      /* set the optional arguments */
     1714
     1715      tr_variantDictFindStr (args_in, TR_KEY_cookies, &cookies, NULL);
     1716
     1717      if (tr_variantDictFindStr (args_in, TR_KEY_download_dir, &str, NULL))
     1718        tr_ctorSetDownloadDir (ctor, TR_FORCE, str);
     1719
     1720      if (tr_variantDictFindBool (args_in, TR_KEY_paused, &boolVal))
     1721        tr_ctorSetPaused (ctor, TR_FORCE, boolVal);
     1722
     1723      if (tr_variantDictFindInt (args_in, TR_KEY_peer_limit, &i))
     1724        tr_ctorSetPeerLimit (ctor, TR_FORCE, i);
     1725
     1726      if (tr_variantDictFindInt (args_in, TR_KEY_bandwidthPriority, &i))
     1727        tr_ctorSetBandwidthPriority (ctor, i);
     1728
     1729      if (tr_variantDictFindList (args_in, TR_KEY_files_unwanted, &l))
     1730        {
     1731          tr_file_index_t fileCount;
     1732          tr_file_index_t * files = fileListFromList (l, &fileCount);
     1733          tr_ctorSetFilesWanted (ctor, files, fileCount, false);
     1734          tr_free (files);
     1735        }
     1736
     1737      if (tr_variantDictFindList (args_in, TR_KEY_files_wanted, &l))
     1738        {
     1739          tr_file_index_t fileCount;
     1740          tr_file_index_t * files = fileListFromList (l, &fileCount);
     1741          tr_ctorSetFilesWanted (ctor, files, fileCount, true);
     1742          tr_free (files);
     1743        }
     1744
     1745      if (tr_variantDictFindList (args_in, TR_KEY_priority_low, &l))
     1746        {
     1747          tr_file_index_t fileCount;
     1748          tr_file_index_t * files = fileListFromList (l, &fileCount);
     1749          tr_ctorSetFilePriorities (ctor, files, fileCount, TR_PRI_LOW);
     1750          tr_free (files);
     1751        }
     1752
     1753      if (tr_variantDictFindList (args_in, TR_KEY_priority_normal, &l))
     1754        {
     1755          tr_file_index_t fileCount;
     1756          tr_file_index_t * files = fileListFromList (l, &fileCount);
     1757          tr_ctorSetFilePriorities (ctor, files, fileCount, TR_PRI_NORMAL);
     1758          tr_free (files);
     1759        }
     1760
     1761      if (tr_variantDictFindList (args_in, TR_KEY_priority_high, &l))
     1762        {
     1763          tr_file_index_t fileCount;
     1764          tr_file_index_t * files = fileListFromList (l, &fileCount);
     1765          tr_ctorSetFilePriorities (ctor, files, fileCount, TR_PRI_HIGH);
     1766          tr_free (files);
     1767        }
     1768
     1769      dbgmsg ("torrentAdd: filename is \"%s\"", filename ? filename : " (null)");
     1770
     1771      if (isCurlURL (filename))
     1772        {
     1773          struct add_torrent_idle_data * d = tr_new0 (struct add_torrent_idle_data, 1);
     1774          d->data = idle_data;
     1775          d->ctor = ctor;
     1776          tr_webRunWithCookies (session, filename, cookies, gotMetadataFromURL, d);
     1777        }
     1778      else
     1779        {
     1780          char * fname = tr_strstrip (tr_strdup (filename));
     1781
     1782          if (fname == NULL)
    17121783            {
    1713                 int len;
    1714                 char * metainfo = tr_base64_decode (metainfo_base64, -1, &len);
    1715                 tr_ctorSetMetainfo (ctor, (uint8_t*)metainfo, len);
    1716                 tr_free (metainfo);
     1784              int len;
     1785              char * metainfo = tr_base64_decode (metainfo_base64, -1, &len);
     1786              tr_ctorSetMetainfo (ctor, (uint8_t*)metainfo, len);
     1787              tr_free (metainfo);
    17171788            }
    1718             else if (!strncmp (fname, "magnet:?", 8))
     1789          else if (!strncmp (fname, "magnet:?", 8))
    17191790            {
    1720                 tr_ctorSetMetainfoFromMagnetLink (ctor, fname);
     1791              tr_ctorSetMetainfoFromMagnetLink (ctor, fname);
    17211792            }
    1722             else
     1793          else
    17231794            {
    1724                 tr_ctorSetMetainfoFromFile (ctor, fname);
     1795              tr_ctorSetMetainfoFromFile (ctor, fname);
    17251796            }
    17261797
    1727             addTorrentImpl (idle_data, ctor);
    1728 
    1729             tr_free (fname);
    1730         }
    1731 
    1732     }
    1733 
    1734     return NULL;
     1798          addTorrentImpl (idle_data, ctor);
     1799
     1800          tr_free (fname);
     1801        }
     1802
     1803    }
     1804
     1805  return NULL;
    17351806}
    17361807
     
    17451816            struct tr_rpc_idle_data  * idle_data UNUSED)
    17461817{
    1747     int64_t      i;
    1748     double       d;
    1749     bool         boolVal;
    1750     const char * str;
    1751 
    1752     assert (idle_data == NULL);
    1753 
    1754     if (tr_variantDictFindInt (args_in, TR_KEY_cache_size_mb, &i))
    1755         tr_sessionSetCacheLimit_MB (session, i);
    1756     if (tr_variantDictFindInt (args_in, TR_KEY_alt_speed_up, &i))
    1757         tr_sessionSetAltSpeed_KBps (session, TR_UP, i);
    1758     if (tr_variantDictFindInt (args_in, TR_KEY_alt_speed_down, &i))
    1759         tr_sessionSetAltSpeed_KBps (session, TR_DOWN, i);
    1760     if (tr_variantDictFindBool (args_in, TR_KEY_alt_speed_enabled, &boolVal))
    1761         tr_sessionUseAltSpeed (session, boolVal);
    1762     if (tr_variantDictFindInt (args_in, TR_KEY_alt_speed_time_begin, &i))
    1763         tr_sessionSetAltSpeedBegin (session, i);
    1764     if (tr_variantDictFindInt (args_in, TR_KEY_alt_speed_time_end, &i))
    1765         tr_sessionSetAltSpeedEnd (session, i);
    1766     if (tr_variantDictFindInt (args_in, TR_KEY_alt_speed_time_day, &i))
    1767         tr_sessionSetAltSpeedDay (session, i);
    1768     if (tr_variantDictFindBool (args_in, TR_KEY_alt_speed_time_enabled, &boolVal))
    1769         tr_sessionUseAltSpeedTime (session, boolVal);
    1770     if (tr_variantDictFindBool (args_in, TR_KEY_blocklist_enabled, &boolVal))
    1771         tr_blocklistSetEnabled (session, boolVal);
    1772     if (tr_variantDictFindStr (args_in, TR_KEY_blocklist_url, &str, NULL))
    1773         tr_blocklistSetURL (session, str);
    1774     if (tr_variantDictFindStr (args_in, TR_KEY_download_dir, &str, NULL))
    1775         tr_sessionSetDownloadDir (session, str);
    1776     if (tr_variantDictFindInt (args_in, TR_KEY_queue_stalled_minutes, &i))
    1777         tr_sessionSetQueueStalledMinutes (session, i);
    1778     if (tr_variantDictFindBool (args_in, TR_KEY_queue_stalled_enabled, &boolVal))
    1779         tr_sessionSetQueueStalledEnabled (session, boolVal);
    1780     if (tr_variantDictFindInt (args_in, TR_KEY_download_queue_size, &i))
    1781         tr_sessionSetQueueSize (session, TR_DOWN, i);
    1782     if (tr_variantDictFindBool (args_in, TR_KEY_download_queue_enabled, &boolVal))
    1783         tr_sessionSetQueueEnabled (session, TR_DOWN, boolVal);
    1784     if (tr_variantDictFindStr (args_in, TR_KEY_incomplete_dir, &str, NULL))
    1785         tr_sessionSetIncompleteDir (session, str);
    1786     if (tr_variantDictFindBool (args_in, TR_KEY_incomplete_dir_enabled, &boolVal))
    1787         tr_sessionSetIncompleteDirEnabled (session, boolVal);
    1788     if (tr_variantDictFindInt (args_in, TR_KEY_peer_limit_global, &i))
    1789         tr_sessionSetPeerLimit (session, i);
    1790     if (tr_variantDictFindInt (args_in, TR_KEY_peer_limit_per_torrent, &i))
    1791         tr_sessionSetPeerLimitPerTorrent (session, i);
    1792     if (tr_variantDictFindBool (args_in, TR_KEY_pex_enabled, &boolVal))
    1793         tr_sessionSetPexEnabled (session, boolVal);
    1794     if (tr_variantDictFindBool (args_in, TR_KEY_dht_enabled, &boolVal))
    1795         tr_sessionSetDHTEnabled (session, boolVal);
    1796     if (tr_variantDictFindBool (args_in, TR_KEY_utp_enabled, &boolVal))
    1797         tr_sessionSetUTPEnabled (session, boolVal);
    1798     if (tr_variantDictFindBool (args_in, TR_KEY_lpd_enabled, &boolVal))
    1799         tr_sessionSetLPDEnabled (session, boolVal);
    1800     if (tr_variantDictFindBool (args_in, TR_KEY_peer_port_random_on_start, &boolVal))
    1801         tr_sessionSetPeerPortRandomOnStart (session, boolVal);
    1802     if (tr_variantDictFindInt (args_in, TR_KEY_peer_port, &i))
    1803         tr_sessionSetPeerPort (session, i);
    1804     if (tr_variantDictFindBool (args_in, TR_KEY_port_forwarding_enabled, &boolVal))
    1805         tr_sessionSetPortForwardingEnabled (session, boolVal);
    1806     if (tr_variantDictFindBool (args_in, TR_KEY_rename_partial_files, &boolVal))
    1807         tr_sessionSetIncompleteFileNamingEnabled (session, boolVal);
    1808     if (tr_variantDictFindReal (args_in, TR_KEY_seedRatioLimit, &d))
    1809         tr_sessionSetRatioLimit (session, d);
    1810     if (tr_variantDictFindBool (args_in, TR_KEY_seedRatioLimited, &boolVal))
    1811         tr_sessionSetRatioLimited (session, boolVal);
    1812     if (tr_variantDictFindInt (args_in, TR_KEY_idle_seeding_limit, &i))
    1813         tr_sessionSetIdleLimit (session, i);
    1814     if (tr_variantDictFindBool (args_in, TR_KEY_idle_seeding_limit_enabled, &boolVal))
    1815         tr_sessionSetIdleLimited (session, boolVal);
    1816     if (tr_variantDictFindBool (args_in, TR_KEY_start_added_torrents, &boolVal))
    1817         tr_sessionSetPaused (session, !boolVal);
    1818     if (tr_variantDictFindBool (args_in, TR_KEY_seed_queue_enabled, &boolVal))
    1819         tr_sessionSetQueueEnabled (session, TR_UP, boolVal);
    1820     if (tr_variantDictFindInt (args_in, TR_KEY_seed_queue_size, &i))
    1821         tr_sessionSetQueueSize (session, TR_UP, i);
    1822     if (tr_variantDictFindStr (args_in, TR_KEY_script_torrent_done_filename, &str, NULL))
    1823         tr_sessionSetTorrentDoneScript (session, str);
    1824     if (tr_variantDictFindBool (args_in, TR_KEY_script_torrent_done_enabled, &boolVal))
    1825         tr_sessionSetTorrentDoneScriptEnabled (session, boolVal);
    1826     if (tr_variantDictFindBool (args_in, TR_KEY_trash_original_torrent_files, &boolVal))
    1827         tr_sessionSetDeleteSource (session, boolVal);
    1828     if (tr_variantDictFindInt (args_in, TR_KEY_speed_limit_down, &i))
    1829         tr_sessionSetSpeedLimit_KBps (session, TR_DOWN, i);
    1830     if (tr_variantDictFindBool (args_in, TR_KEY_speed_limit_down_enabled, &boolVal))
    1831         tr_sessionLimitSpeed (session, TR_DOWN, boolVal);
    1832     if (tr_variantDictFindInt (args_in, TR_KEY_speed_limit_up, &i))
    1833         tr_sessionSetSpeedLimit_KBps (session, TR_UP, i);
    1834     if (tr_variantDictFindBool (args_in, TR_KEY_speed_limit_up_enabled, &boolVal))
    1835         tr_sessionLimitSpeed (session, TR_UP, boolVal);
    1836     if (tr_variantDictFindStr (args_in, TR_KEY_encryption, &str, NULL)) {
    1837         if (!strcmp (str, "required"))
    1838             tr_sessionSetEncryption (session, TR_ENCRYPTION_REQUIRED);
    1839         else if (!strcmp (str, "tolerated"))
    1840             tr_sessionSetEncryption (session, TR_CLEAR_PREFERRED);
    1841         else
    1842             tr_sessionSetEncryption (session, TR_ENCRYPTION_PREFERRED);
    1843     }
    1844 
    1845     notify (session, TR_RPC_SESSION_CHANGED, NULL);
    1846 
    1847     return NULL;
     1818  int64_t i;
     1819  double d;
     1820  bool boolVal;
     1821  const char * str;
     1822
     1823  assert (idle_data == NULL);
     1824
     1825  if (tr_variantDictFindInt (args_in, TR_KEY_cache_size_mb, &i))
     1826    tr_sessionSetCacheLimit_MB (session, i);
     1827
     1828  if (tr_variantDictFindInt (args_in, TR_KEY_alt_speed_up, &i))
     1829    tr_sessionSetAltSpeed_KBps (session, TR_UP, i);
     1830
     1831  if (tr_variantDictFindInt (args_in, TR_KEY_alt_speed_down, &i))
     1832    tr_sessionSetAltSpeed_KBps (session, TR_DOWN, i);
     1833
     1834  if (tr_variantDictFindBool (args_in, TR_KEY_alt_speed_enabled, &boolVal))
     1835    tr_sessionUseAltSpeed (session, boolVal);
     1836
     1837  if (tr_variantDictFindInt (args_in, TR_KEY_alt_speed_time_begin, &i))
     1838    tr_sessionSetAltSpeedBegin (session, i);
     1839
     1840  if (tr_variantDictFindInt (args_in, TR_KEY_alt_speed_time_end, &i))
     1841    tr_sessionSetAltSpeedEnd (session, i);
     1842
     1843  if (tr_variantDictFindInt (args_in, TR_KEY_alt_speed_time_day, &i))
     1844    tr_sessionSetAltSpeedDay (session, i);
     1845
     1846  if (tr_variantDictFindBool (args_in, TR_KEY_alt_speed_time_enabled, &boolVal))
     1847    tr_sessionUseAltSpeedTime (session, boolVal);
     1848
     1849  if (tr_variantDictFindBool (args_in, TR_KEY_blocklist_enabled, &boolVal))
     1850    tr_blocklistSetEnabled (session, boolVal);
     1851
     1852  if (tr_variantDictFindStr (args_in, TR_KEY_blocklist_url, &str, NULL))
     1853    tr_blocklistSetURL (session, str);
     1854
     1855  if (tr_variantDictFindStr (args_in, TR_KEY_download_dir, &str, NULL))
     1856    tr_sessionSetDownloadDir (session, str);
     1857
     1858  if (tr_variantDictFindInt (args_in, TR_KEY_queue_stalled_minutes, &i))
     1859    tr_sessionSetQueueStalledMinutes (session, i);
     1860
     1861  if (tr_variantDictFindBool (args_in, TR_KEY_queue_stalled_enabled, &boolVal))
     1862    tr_sessionSetQueueStalledEnabled (session, boolVal);
     1863
     1864  if (tr_variantDictFindInt (args_in, TR_KEY_download_queue_size, &i))
     1865    tr_sessionSetQueueSize (session, TR_DOWN, i);
     1866
     1867  if (tr_variantDictFindBool (args_in, TR_KEY_download_queue_enabled, &boolVal))
     1868    tr_sessionSetQueueEnabled (session, TR_DOWN, boolVal);
     1869
     1870  if (tr_variantDictFindStr (args_in, TR_KEY_incomplete_dir, &str, NULL))
     1871    tr_sessionSetIncompleteDir (session, str);
     1872
     1873  if (tr_variantDictFindBool (args_in, TR_KEY_incomplete_dir_enabled, &boolVal))
     1874    tr_sessionSetIncompleteDirEnabled (session, boolVal);
     1875
     1876  if (tr_variantDictFindInt (args_in, TR_KEY_peer_limit_global, &i))
     1877    tr_sessionSetPeerLimit (session, i);
     1878
     1879  if (tr_variantDictFindInt (args_in, TR_KEY_peer_limit_per_torrent, &i))
     1880    tr_sessionSetPeerLimitPerTorrent (session, i);
     1881
     1882  if (tr_variantDictFindBool (args_in, TR_KEY_pex_enabled, &boolVal))
     1883    tr_sessionSetPexEnabled (session, boolVal);
     1884
     1885  if (tr_variantDictFindBool (args_in, TR_KEY_dht_enabled, &boolVal))
     1886    tr_sessionSetDHTEnabled (session, boolVal);
     1887
     1888  if (tr_variantDictFindBool (args_in, TR_KEY_utp_enabled, &boolVal))
     1889    tr_sessionSetUTPEnabled (session, boolVal);
     1890
     1891  if (tr_variantDictFindBool (args_in, TR_KEY_lpd_enabled, &boolVal))
     1892    tr_sessionSetLPDEnabled (session, boolVal);
     1893
     1894  if (tr_variantDictFindBool (args_in, TR_KEY_peer_port_random_on_start, &boolVal))
     1895    tr_sessionSetPeerPortRandomOnStart (session, boolVal);
     1896
     1897  if (tr_variantDictFindInt (args_in, TR_KEY_peer_port, &i))
     1898    tr_sessionSetPeerPort (session, i);
     1899
     1900  if (tr_variantDictFindBool (args_in, TR_KEY_port_forwarding_enabled, &boolVal))
     1901    tr_sessionSetPortForwardingEnabled (session, boolVal);
     1902
     1903  if (tr_variantDictFindBool (args_in, TR_KEY_rename_partial_files, &boolVal))
     1904    tr_sessionSetIncompleteFileNamingEnabled (session, boolVal);
     1905
     1906  if (tr_variantDictFindReal (args_in, TR_KEY_seedRatioLimit, &d))
     1907    tr_sessionSetRatioLimit (session, d);
     1908
     1909  if (tr_variantDictFindBool (args_in, TR_KEY_seedRatioLimited, &boolVal))
     1910    tr_sessionSetRatioLimited (session, boolVal);
     1911
     1912  if (tr_variantDictFindInt (args_in, TR_KEY_idle_seeding_limit, &i))
     1913    tr_sessionSetIdleLimit (session, i);
     1914
     1915  if (tr_variantDictFindBool (args_in, TR_KEY_idle_seeding_limit_enabled, &boolVal))
     1916    tr_sessionSetIdleLimited (session, boolVal);
     1917
     1918  if (tr_variantDictFindBool (args_in, TR_KEY_start_added_torrents, &boolVal))
     1919    tr_sessionSetPaused (session, !boolVal);
     1920
     1921  if (tr_variantDictFindBool (args_in, TR_KEY_seed_queue_enabled, &boolVal))
     1922    tr_sessionSetQueueEnabled (session, TR_UP, boolVal);
     1923
     1924  if (tr_variantDictFindInt (args_in, TR_KEY_seed_queue_size, &i))
     1925    tr_sessionSetQueueSize (session, TR_UP, i);
     1926
     1927  if (tr_variantDictFindStr (args_in, TR_KEY_script_torrent_done_filename, &str, NULL))
     1928    tr_sessionSetTorrentDoneScript (session, str);
     1929
     1930  if (tr_variantDictFindBool (args_in, TR_KEY_script_torrent_done_enabled, &boolVal))
     1931    tr_sessionSetTorrentDoneScriptEnabled (session, boolVal);
     1932
     1933  if (tr_variantDictFindBool (args_in, TR_KEY_trash_original_torrent_files, &boolVal))
     1934    tr_sessionSetDeleteSource (session, boolVal);
     1935
     1936  if (tr_variantDictFindInt (args_in, TR_KEY_speed_limit_down, &i))
     1937    tr_sessionSetSpeedLimit_KBps (session, TR_DOWN, i);
     1938
     1939  if (tr_variantDictFindBool (args_in, TR_KEY_speed_limit_down_enabled, &boolVal))
     1940    tr_sessionLimitSpeed (session, TR_DOWN, boolVal);
     1941
     1942  if (tr_variantDictFindInt (args_in, TR_KEY_speed_limit_up, &i))
     1943    tr_sessionSetSpeedLimit_KBps (session, TR_UP, i);
     1944
     1945  if (tr_variantDictFindBool (args_in, TR_KEY_speed_limit_up_enabled, &boolVal))
     1946    tr_sessionLimitSpeed (session, TR_UP, boolVal);
     1947
     1948  if (tr_variantDictFindStr (args_in, TR_KEY_encryption, &str, NULL))
     1949    {
     1950      if (!tr_strcmp0 (str, "required"))
     1951        tr_sessionSetEncryption (session, TR_ENCRYPTION_REQUIRED);
     1952      else if (!tr_strcmp0 (str, "tolerated"))
     1953        tr_sessionSetEncryption (session, TR_CLEAR_PREFERRED);
     1954      else
     1955        tr_sessionSetEncryption (session, TR_ENCRYPTION_PREFERRED);
     1956    }
     1957
     1958  notify (session, TR_RPC_SESSION_CHANGED, NULL);
     1959
     1960  return NULL;
    18481961}
    18491962
    18501963static const char*
    18511964sessionStats (tr_session               * session,
    1852               tr_variant                  * args_in UNUSED,
    1853               tr_variant                  * args_out,
     1965              tr_variant               * args_in UNUSED,
     1966              tr_variant               * args_out,
    18541967              struct tr_rpc_idle_data  * idle_data UNUSED)
    18551968{
    1856     int running = 0;
    1857     int total = 0;
    1858     tr_variant * d;
    1859     tr_session_stats currentStats = { 0.0f, 0, 0, 0, 0, 0 };
    1860     tr_session_stats cumulativeStats = { 0.0f, 0, 0, 0, 0, 0 };
    1861     tr_torrent * tor = NULL;
    1862 
    1863     assert (idle_data == NULL);
    1864 
    1865     while ((tor = tr_torrentNext (session, tor))) {
    1866         ++total;
    1867         if (tor->isRunning)
    1868             ++running;
    1869     }
    1870 
    1871     tr_sessionGetStats (session, &currentStats);
    1872     tr_sessionGetCumulativeStats (session, &cumulativeStats);
    1873 
    1874     tr_variantDictAddInt  (args_out, TR_KEY_activeTorrentCount, running);
    1875     tr_variantDictAddReal (args_out, TR_KEY_downloadSpeed, tr_sessionGetPieceSpeed_Bps (session, TR_DOWN));
    1876     tr_variantDictAddInt  (args_out, TR_KEY_pausedTorrentCount, total - running);
    1877     tr_variantDictAddInt  (args_out, TR_KEY_torrentCount, total);
    1878     tr_variantDictAddReal (args_out, TR_KEY_uploadSpeed, tr_sessionGetPieceSpeed_Bps (session, TR_UP));
    1879 
    1880     d = tr_variantDictAddDict (args_out, TR_KEY_cumulative_stats, 5);
    1881     tr_variantDictAddInt (d, TR_KEY_downloadedBytes, cumulativeStats.downloadedBytes);
    1882     tr_variantDictAddInt (d, TR_KEY_filesAdded, cumulativeStats.filesAdded);
    1883     tr_variantDictAddInt (d, TR_KEY_secondsActive, cumulativeStats.secondsActive);
    1884     tr_variantDictAddInt (d, TR_KEY_sessionCount, cumulativeStats.sessionCount);
    1885     tr_variantDictAddInt (d, TR_KEY_uploadedBytes, cumulativeStats.uploadedBytes);
    1886 
    1887     d = tr_variantDictAddDict (args_out, TR_KEY_current_stats, 5);
    1888     tr_variantDictAddInt (d, TR_KEY_downloadedBytes, currentStats.downloadedBytes);
    1889     tr_variantDictAddInt (d, TR_KEY_filesAdded, currentStats.filesAdded);
    1890     tr_variantDictAddInt (d, TR_KEY_secondsActive, currentStats.secondsActive);
    1891     tr_variantDictAddInt (d, TR_KEY_sessionCount, currentStats.sessionCount);
    1892     tr_variantDictAddInt (d, TR_KEY_uploadedBytes, currentStats.uploadedBytes);
    1893 
    1894     return NULL;
     1969  int running = 0;
     1970  int total = 0;
     1971  tr_variant * d;
     1972  tr_session_stats currentStats = { 0.0f, 0, 0, 0, 0, 0 };
     1973  tr_session_stats cumulativeStats = { 0.0f, 0, 0, 0, 0, 0 };
     1974  tr_torrent * tor = NULL;
     1975
     1976  assert (idle_data == NULL);
     1977
     1978  while ((tor = tr_torrentNext (session, tor)))
     1979    {
     1980      ++total;
     1981
     1982      if (tor->isRunning)
     1983        ++running;
     1984    }
     1985
     1986  tr_sessionGetStats (session, &currentStats);
     1987  tr_sessionGetCumulativeStats (session, &cumulativeStats);
     1988
     1989  tr_variantDictAddInt  (args_out, TR_KEY_activeTorrentCount, running);
     1990  tr_variantDictAddReal (args_out, TR_KEY_downloadSpeed, tr_sessionGetPieceSpeed_Bps (session, TR_DOWN));
     1991  tr_variantDictAddInt  (args_out, TR_KEY_pausedTorrentCount, total - running);
     1992  tr_variantDictAddInt  (args_out, TR_KEY_torrentCount, total);
     1993  tr_variantDictAddReal (args_out, TR_KEY_uploadSpeed, tr_sessionGetPieceSpeed_Bps (session, TR_UP));
     1994
     1995  d = tr_variantDictAddDict (args_out, TR_KEY_cumulative_stats, 5);
     1996  tr_variantDictAddInt (d, TR_KEY_downloadedBytes, cumulativeStats.downloadedBytes);
     1997  tr_variantDictAddInt (d, TR_KEY_filesAdded, cumulativeStats.filesAdded);
     1998  tr_variantDictAddInt (d, TR_KEY_secondsActive, cumulativeStats.secondsActive);
     1999  tr_variantDictAddInt (d, TR_KEY_sessionCount, cumulativeStats.sessionCount);
     2000  tr_variantDictAddInt (d, TR_KEY_uploadedBytes, cumulativeStats.uploadedBytes);
     2001
     2002  d = tr_variantDictAddDict (args_out, TR_KEY_current_stats, 5);
     2003  tr_variantDictAddInt (d, TR_KEY_downloadedBytes, currentStats.downloadedBytes);
     2004  tr_variantDictAddInt (d, TR_KEY_filesAdded, currentStats.filesAdded);
     2005  tr_variantDictAddInt (d, TR_KEY_secondsActive, currentStats.secondsActive);
     2006  tr_variantDictAddInt (d, TR_KEY_sessionCount, currentStats.sessionCount);
     2007  tr_variantDictAddInt (d, TR_KEY_uploadedBytes, currentStats.uploadedBytes);
     2008
     2009  return NULL;
    18952010}
    18962011
     
    19012016            struct tr_rpc_idle_data  * idle_data UNUSED)
    19022017{
    1903     const char * str;
    1904     tr_variant * d = args_out;
    1905 
    1906     assert (idle_data == NULL);
    1907     tr_variantDictAddInt  (d, TR_KEY_alt_speed_up, tr_sessionGetAltSpeed_KBps (s,TR_UP));
    1908     tr_variantDictAddInt  (d, TR_KEY_alt_speed_down, tr_sessionGetAltSpeed_KBps (s,TR_DOWN));
    1909     tr_variantDictAddBool (d, TR_KEY_alt_speed_enabled, tr_sessionUsesAltSpeed (s));
    1910     tr_variantDictAddInt  (d, TR_KEY_alt_speed_time_begin, tr_sessionGetAltSpeedBegin (s));
    1911     tr_variantDictAddInt  (d, TR_KEY_alt_speed_time_end,tr_sessionGetAltSpeedEnd (s));
    1912     tr_variantDictAddInt  (d, TR_KEY_alt_speed_time_day,tr_sessionGetAltSpeedDay (s));
    1913     tr_variantDictAddBool (d, TR_KEY_alt_speed_time_enabled, tr_sessionUsesAltSpeedTime (s));
    1914     tr_variantDictAddBool (d, TR_KEY_blocklist_enabled, tr_blocklistIsEnabled (s));
    1915     tr_variantDictAddStr  (d, TR_KEY_blocklist_url, tr_blocklistGetURL (s));
    1916     tr_variantDictAddInt  (d, TR_KEY_cache_size_mb, tr_sessionGetCacheLimit_MB (s));
    1917     tr_variantDictAddInt  (d, TR_KEY_blocklist_size, tr_blocklistGetRuleCount (s));
    1918     tr_variantDictAddStr  (d, TR_KEY_config_dir, tr_sessionGetConfigDir (s));
    1919     tr_variantDictAddStr  (d, TR_KEY_download_dir, tr_sessionGetDownloadDir (s));
    1920     tr_variantDictAddInt  (d, TR_KEY_download_dir_free_space, tr_device_info_get_free_space (s->downloadDir));
    1921     tr_variantDictAddBool (d, TR_KEY_download_queue_enabled, tr_sessionGetQueueEnabled (s, TR_DOWN));
    1922     tr_variantDictAddInt  (d, TR_KEY_download_queue_size, tr_sessionGetQueueSize (s, TR_DOWN));
    1923     tr_variantDictAddInt  (d, TR_KEY_peer_limit_global, tr_sessionGetPeerLimit (s));
    1924     tr_variantDictAddInt  (d, TR_KEY_peer_limit_per_torrent, tr_sessionGetPeerLimitPerTorrent (s));
    1925     tr_variantDictAddStr  (d, TR_KEY_incomplete_dir, tr_sessionGetIncompleteDir (s));
    1926     tr_variantDictAddBool (d, TR_KEY_incomplete_dir_enabled, tr_sessionIsIncompleteDirEnabled (s));
    1927     tr_variantDictAddBool (d, TR_KEY_pex_enabled, tr_sessionIsPexEnabled (s));
    1928     tr_variantDictAddBool (d, TR_KEY_utp_enabled, tr_sessionIsUTPEnabled (s));
    1929     tr_variantDictAddBool (d, TR_KEY_dht_enabled, tr_sessionIsDHTEnabled (s));
    1930     tr_variantDictAddBool (d, TR_KEY_lpd_enabled, tr_sessionIsLPDEnabled (s));
    1931     tr_variantDictAddInt  (d, TR_KEY_peer_port, tr_sessionGetPeerPort (s));
    1932     tr_variantDictAddBool (d, TR_KEY_peer_port_random_on_start, tr_sessionGetPeerPortRandomOnStart (s));
    1933     tr_variantDictAddBool (d, TR_KEY_port_forwarding_enabled, tr_sessionIsPortForwardingEnabled (s));
    1934     tr_variantDictAddBool (d, TR_KEY_rename_partial_files, tr_sessionIsIncompleteFileNamingEnabled (s));
    1935     tr_variantDictAddInt  (d, TR_KEY_rpc_version, RPC_VERSION);
    1936     tr_variantDictAddInt  (d, TR_KEY_rpc_version_minimum, RPC_VERSION_MIN);
    1937     tr_variantDictAddReal (d, TR_KEY_seedRatioLimit, tr_sessionGetRatioLimit (s));
    1938     tr_variantDictAddBool (d, TR_KEY_seedRatioLimited, tr_sessionIsRatioLimited (s));
    1939     tr_variantDictAddInt  (d, TR_KEY_idle_seeding_limit, tr_sessionGetIdleLimit (s));
    1940     tr_variantDictAddBool (d, TR_KEY_idle_seeding_limit_enabled, tr_sessionIsIdleLimited (s));
    1941     tr_variantDictAddBool (d, TR_KEY_seed_queue_enabled, tr_sessionGetQueueEnabled (s, TR_UP));
    1942     tr_variantDictAddInt  (d, TR_KEY_seed_queue_size, tr_sessionGetQueueSize (s, TR_UP));
    1943     tr_variantDictAddBool (d, TR_KEY_start_added_torrents, !tr_sessionGetPaused (s));
    1944     tr_variantDictAddBool (d, TR_KEY_trash_original_torrent_files, tr_sessionGetDeleteSource (s));
    1945     tr_variantDictAddInt  (d, TR_KEY_speed_limit_up, tr_sessionGetSpeedLimit_KBps (s, TR_UP));
    1946     tr_variantDictAddBool (d, TR_KEY_speed_limit_up_enabled, tr_sessionIsSpeedLimited (s, TR_UP));
    1947     tr_variantDictAddInt  (d, TR_KEY_speed_limit_down, tr_sessionGetSpeedLimit_KBps (s, TR_DOWN));
    1948     tr_variantDictAddBool (d, TR_KEY_speed_limit_down_enabled, tr_sessionIsSpeedLimited (s, TR_DOWN));
    1949     tr_variantDictAddStr  (d, TR_KEY_script_torrent_done_filename, tr_sessionGetTorrentDoneScript (s));
    1950     tr_variantDictAddBool (d, TR_KEY_script_torrent_done_enabled, tr_sessionIsTorrentDoneScriptEnabled (s));
    1951     tr_variantDictAddBool (d, TR_KEY_queue_stalled_enabled, tr_sessionGetQueueStalledEnabled (s));
    1952     tr_variantDictAddInt  (d, TR_KEY_queue_stalled_minutes, tr_sessionGetQueueStalledMinutes (s));
    1953     tr_formatter_get_units (tr_variantDictAddDict (d, TR_KEY_units, 0));
    1954     tr_variantDictAddStr  (d, TR_KEY_version, LONG_VERSION_STRING);
    1955     switch (tr_sessionGetEncryption (s)) {
    1956         case TR_CLEAR_PREFERRED: str = "tolerated"; break;
    1957         case TR_ENCRYPTION_REQUIRED: str = "required"; break;
    1958         default: str = "preferred"; break;
    1959     }
    1960     tr_variantDictAddStr (d, TR_KEY_encryption, str);
    1961 
    1962     return NULL;
     2018  const char * str;
     2019  tr_variant * d = args_out;
     2020
     2021  assert (idle_data == NULL);
     2022  tr_variantDictAddInt  (d, TR_KEY_alt_speed_up, tr_sessionGetAltSpeed_KBps (s,TR_UP));
     2023  tr_variantDictAddInt  (d, TR_KEY_alt_speed_down, tr_sessionGetAltSpeed_KBps (s,TR_DOWN));
     2024  tr_variantDictAddBool (d, TR_KEY_alt_speed_enabled, tr_sessionUsesAltSpeed (s));
     2025  tr_variantDictAddInt  (d, TR_KEY_alt_speed_time_begin, tr_sessionGetAltSpeedBegin (s));
     2026  tr_variantDictAddInt  (d, TR_KEY_alt_speed_time_end,tr_sessionGetAltSpeedEnd (s));
     2027  tr_variantDictAddInt  (d, TR_KEY_alt_speed_time_day,tr_sessionGetAltSpeedDay (s));
     2028  tr_variantDictAddBool (d, TR_KEY_alt_speed_time_enabled, tr_sessionUsesAltSpeedTime (s));
     2029  tr_variantDictAddBool (d, TR_KEY_blocklist_enabled, tr_blocklistIsEnabled (s));
     2030  tr_variantDictAddStr  (d, TR_KEY_blocklist_url, tr_blocklistGetURL (s));
     2031  tr_variantDictAddInt  (d, TR_KEY_cache_size_mb, tr_sessionGetCacheLimit_MB (s));
     2032  tr_variantDictAddInt  (d, TR_KEY_blocklist_size, tr_blocklistGetRuleCount (s));
     2033  tr_variantDictAddStr  (d, TR_KEY_config_dir, tr_sessionGetConfigDir (s));
     2034  tr_variantDictAddStr  (d, TR_KEY_download_dir, tr_sessionGetDownloadDir (s));
     2035  tr_variantDictAddInt  (d, TR_KEY_download_dir_free_space, tr_device_info_get_free_space (s->downloadDir));
     2036  tr_variantDictAddBool (d, TR_KEY_download_queue_enabled, tr_sessionGetQueueEnabled (s, TR_DOWN));
     2037  tr_variantDictAddInt  (d, TR_KEY_download_queue_size, tr_sessionGetQueueSize (s, TR_DOWN));
     2038  tr_variantDictAddInt  (d, TR_KEY_peer_limit_global, tr_sessionGetPeerLimit (s));
     2039  tr_variantDictAddInt  (d, TR_KEY_peer_limit_per_torrent, tr_sessionGetPeerLimitPerTorrent (s));
     2040  tr_variantDictAddStr  (d, TR_KEY_incomplete_dir, tr_sessionGetIncompleteDir (s));
     2041  tr_variantDictAddBool (d, TR_KEY_incomplete_dir_enabled, tr_sessionIsIncompleteDirEnabled (s));
     2042  tr_variantDictAddBool (d, TR_KEY_pex_enabled, tr_sessionIsPexEnabled (s));
     2043  tr_variantDictAddBool (d, TR_KEY_utp_enabled, tr_sessionIsUTPEnabled (s));
     2044  tr_variantDictAddBool (d, TR_KEY_dht_enabled, tr_sessionIsDHTEnabled (s));
     2045  tr_variantDictAddBool (d, TR_KEY_lpd_enabled, tr_sessionIsLPDEnabled (s));
     2046  tr_variantDictAddInt  (d, TR_KEY_peer_port, tr_sessionGetPeerPort (s));
     2047  tr_variantDictAddBool (d, TR_KEY_peer_port_random_on_start, tr_sessionGetPeerPortRandomOnStart (s));
     2048  tr_variantDictAddBool (d, TR_KEY_port_forwarding_enabled, tr_sessionIsPortForwardingEnabled (s));
     2049  tr_variantDictAddBool (d, TR_KEY_rename_partial_files, tr_sessionIsIncompleteFileNamingEnabled (s));
     2050  tr_variantDictAddInt  (d, TR_KEY_rpc_version, RPC_VERSION);
     2051  tr_variantDictAddInt  (d, TR_KEY_rpc_version_minimum, RPC_VERSION_MIN);
     2052  tr_variantDictAddReal (d, TR_KEY_seedRatioLimit, tr_sessionGetRatioLimit (s));
     2053  tr_variantDictAddBool (d, TR_KEY_seedRatioLimited, tr_sessionIsRatioLimited (s));
     2054  tr_variantDictAddInt  (d, TR_KEY_idle_seeding_limit, tr_sessionGetIdleLimit (s));
     2055  tr_variantDictAddBool (d, TR_KEY_idle_seeding_limit_enabled, tr_sessionIsIdleLimited (s));
     2056  tr_variantDictAddBool (d, TR_KEY_seed_queue_enabled, tr_sessionGetQueueEnabled (s, TR_UP));
     2057  tr_variantDictAddInt  (d, TR_KEY_seed_queue_size, tr_sessionGetQueueSize (s, TR_UP));
     2058  tr_variantDictAddBool (d, TR_KEY_start_added_torrents, !tr_sessionGetPaused (s));
     2059  tr_variantDictAddBool (d, TR_KEY_trash_original_torrent_files, tr_sessionGetDeleteSource (s));
     2060  tr_variantDictAddInt  (d, TR_KEY_speed_limit_up, tr_sessionGetSpeedLimit_KBps (s, TR_UP));
     2061  tr_variantDictAddBool (d, TR_KEY_speed_limit_up_enabled, tr_sessionIsSpeedLimited (s, TR_UP));
     2062  tr_variantDictAddInt  (d, TR_KEY_speed_limit_down, tr_sessionGetSpeedLimit_KBps (s, TR_DOWN));
     2063  tr_variantDictAddBool (d, TR_KEY_speed_limit_down_enabled, tr_sessionIsSpeedLimited (s, TR_DOWN));
     2064  tr_variantDictAddStr  (d, TR_KEY_script_torrent_done_filename, tr_sessionGetTorrentDoneScript (s));
     2065  tr_variantDictAddBool (d, TR_KEY_script_torrent_done_enabled, tr_sessionIsTorrentDoneScriptEnabled (s));
     2066  tr_variantDictAddBool (d, TR_KEY_queue_stalled_enabled, tr_sessionGetQueueStalledEnabled (s));
     2067  tr_variantDictAddInt  (d, TR_KEY_queue_stalled_minutes, tr_sessionGetQueueStalledMinutes (s));
     2068  tr_formatter_get_units (tr_variantDictAddDict (d, TR_KEY_units, 0));
     2069  tr_variantDictAddStr  (d, TR_KEY_version, LONG_VERSION_STRING);
     2070  switch (tr_sessionGetEncryption (s))
     2071    {
     2072      case TR_CLEAR_PREFERRED: str = "tolerated"; break;
     2073      case TR_ENCRYPTION_REQUIRED: str = "required"; break;
     2074      default: str = "preferred"; break;
     2075    }
     2076  tr_variantDictAddStr (d, TR_KEY_encryption, str);
     2077
     2078  return NULL;
    19632079}
    19642080
     
    19962112static const char*
    19972113sessionClose (tr_session               * session,
    1998               tr_variant                  * args_in UNUSED,
    1999               tr_variant                  * args_out UNUSED,
     2114              tr_variant               * args_in UNUSED,
     2115              tr_variant               * args_out UNUSED,
    20002116              struct tr_rpc_idle_data  * idle_data UNUSED)
    20012117{
    2002     notify (session, TR_RPC_SESSION_CLOSE, NULL);
    2003     return NULL;
     2118  notify (session, TR_RPC_SESSION_CLOSE, NULL);
     2119  return NULL;
    20042120}
    20052121
     
    20122128static struct method
    20132129{
    2014     const char *  name;
    2015     bool          immediate;
    2016     handler       func;
     2130  const char *  name;
     2131  bool          immediate;
     2132  handler       func;
    20172133}
    20182134methods[] =
    20192135{
    2020     { "port-test",             false, portTest            },
    2021     { "blocklist-update",      false, blocklistUpdate     },
    2022     { "free-space",            true,  freeSpace           },
    2023     { "session-close",         true,  sessionClose        },
    2024     { "session-get",           true,  sessionGet          },
    2025     { "session-set",           true,  sessionSet          },
    2026     { "session-stats",         true,  sessionStats        },
    2027     { "torrent-add",           false, torrentAdd          },
    2028     { "torrent-get",           true,  torrentGet          },
    2029     { "torrent-remove",        true,  torrentRemove       },
    2030     { "torrent-rename-path",   false, torrentRenamePath   },
    2031     { "torrent-set",           true,  torrentSet          },
    2032     { "torrent-set-location",  true,  torrentSetLocation  },
    2033     { "torrent-start",         true,  torrentStart        },
    2034     { "torrent-start-now",     true,  torrentStartNow     },
    2035     { "torrent-stop",          true,  torrentStop         },
    2036     { "torrent-verify",        true,  torrentVerify       },
    2037     { "torrent-reannounce",    true,  torrentReannounce   },
    2038     { "queue-move-top",        true,  queueMoveTop        },
    2039     { "queue-move-up",         true,  queueMoveUp         },
    2040     { "queue-move-down",       true,  queueMoveDown       },
    2041     { "queue-move-bottom",     true,  queueMoveBottom     }
     2136  { "port-test",             false, portTest            },
     2137  { "blocklist-update",      false, blocklistUpdate     },
     2138  { "free-space",            true,  freeSpace           },
     2139  { "session-close",         true,  sessionClose        },
     2140  { "session-get",           true,  sessionGet          },
     2141  { "session-set",           true,  sessionSet          },
     2142  { "session-stats",         true,  sessionStats        },
     2143  { "torrent-add",           false, torrentAdd          },
     2144  { "torrent-get",           true,  torrentGet          },
     2145  { "torrent-remove",        true,  torrentRemove       },
     2146  { "torrent-rename-path",   false, torrentRenamePath   },
     2147  { "torrent-set",           true,  torrentSet          },
     2148  { "torrent-set-location",  true,  torrentSetLocation  },
     2149  { "torrent-start",         true,  torrentStart        },
     2150  { "torrent-start-now",     true,  torrentStartNow     },
     2151  { "torrent-stop",          true,  torrentStop         },
     2152  { "torrent-verify",        true,  torrentVerify       },
     2153  { "torrent-reannounce",    true,  torrentReannounce   },
     2154  { "queue-move-top",        true,  queueMoveTop        },
     2155  { "queue-move-up",         true,  queueMoveUp         },
     2156  { "queue-move-down",       true,  queueMoveDown       },
     2157  { "queue-move-bottom",     true,  queueMoveBottom     }
    20422158};
    20432159
     
    20552171              void                   * callback_user_data)
    20562172{
    2057     int i;
    2058     const char * str;
    2059     tr_variant * args_in = tr_variantDictFind (request, TR_KEY_arguments);
    2060     const char * result = NULL;
    2061 
    2062     if (callback == NULL)
    2063         callback = noop_response_callback;
    2064 
    2065     /* parse the request */
    2066     if (!tr_variantDictFindStr (request, TR_KEY_method, &str, NULL))
    2067         result = "no method name";
    2068     else {
    2069         const int n = TR_N_ELEMENTS (methods);
    2070         for (i = 0; i < n; ++i)
    2071             if (!strcmp (str, methods[i].name))
    2072                 break;
    2073         if (i ==n)
    2074             result = "method name not recognized";
    2075     }
    2076 
    2077     /* if we couldn't figure out which method to use, return an error */
    2078     if (result != NULL)
    2079     {
    2080         int64_t tag;
    2081         tr_variant response;
    2082         struct evbuffer * buf;
    2083 
    2084         tr_variantInitDict (&response, 3);
    2085         tr_variantDictAddDict (&response, TR_KEY_arguments, 0);
    2086         tr_variantDictAddStr (&response, TR_KEY_result, result);
    2087         if (tr_variantDictFindInt (request, TR_KEY_tag, &tag))
    2088             tr_variantDictAddInt (&response, TR_KEY_tag, tag);
    2089 
    2090         buf = tr_variantToBuf (&response, TR_VARIANT_FMT_JSON_LEAN);
     2173  int i;
     2174  const char * str;
     2175  tr_variant * args_in = tr_variantDictFind (request, TR_KEY_arguments);
     2176  const char * result = NULL;
     2177
     2178  if (callback == NULL)
     2179    callback = noop_response_callback;
     2180
     2181  /* parse the request */
     2182  if (!tr_variantDictFindStr (request, TR_KEY_method, &str, NULL))
     2183    {
     2184      result = "no method name";
     2185    }
     2186  else
     2187    {
     2188      const int n = TR_N_ELEMENTS (methods);
     2189
     2190      for (i=0; i<n; ++i)
     2191        if (!strcmp (str, methods[i].name))
     2192          break;
     2193
     2194      if (i ==n)
     2195        result = "method name not recognized";
     2196    }
     2197
     2198  /* if we couldn't figure out which method to use, return an error */
     2199  if (result != NULL)
     2200    {
     2201      int64_t tag;
     2202      tr_variant response;
     2203      struct evbuffer * buf;
     2204
     2205      tr_variantInitDict (&response, 3);
     2206      tr_variantDictAddDict (&response, TR_KEY_arguments, 0);
     2207      tr_variantDictAddStr (&response, TR_KEY_result, result);
     2208      if (tr_variantDictFindInt (request, TR_KEY_tag, &tag))
     2209        tr_variantDictAddInt (&response, TR_KEY_tag, tag);
     2210
     2211      buf = tr_variantToBuf (&response, TR_VARIANT_FMT_JSON_LEAN);
    20912212      (*callback)(session, buf, callback_user_data);
    2092         evbuffer_free (buf);
    2093 
    2094         tr_variantFree (&response);
    2095     }
    2096     else if (methods[i].immediate)
    2097     {
    2098         int64_t tag;
    2099         tr_variant response;
    2100         tr_variant * args_out;
    2101         struct evbuffer * buf;
    2102 
    2103         tr_variantInitDict (&response, 3);
    2104         args_out = tr_variantDictAddDict (&response, TR_KEY_arguments, 0);
    2105         result = (*methods[i].func)(session, args_in, args_out, NULL);
    2106         if (result == NULL)
    2107             result = "success";
    2108         tr_variantDictAddStr (&response, TR_KEY_result, result);
    2109         if (tr_variantDictFindInt (request, TR_KEY_tag, &tag))
    2110             tr_variantDictAddInt (&response, TR_KEY_tag, tag);
    2111 
    2112         buf = tr_variantToBuf (&response, TR_VARIANT_FMT_JSON_LEAN);
    2113         (*callback)(session, buf, callback_user_data);
    2114         evbuffer_free (buf);
    2115 
    2116         tr_variantFree (&response);
    2117     }
    2118     else
    2119     {
    2120         int64_t tag;
    2121         struct tr_rpc_idle_data * data = tr_new0 (struct tr_rpc_idle_data, 1);
    2122         data->session = session;
    2123         data->response = tr_new0 (tr_variant, 1);
    2124         tr_variantInitDict (data->response, 3);
    2125         if (tr_variantDictFindInt (request, TR_KEY_tag, &tag))
    2126             tr_variantDictAddInt (data->response, TR_KEY_tag, tag);
    2127         data->args_out = tr_variantDictAddDict (data->response, TR_KEY_arguments, 0);
    2128         data->callback = callback;
    2129         data->callback_user_data = callback_user_data;
    2130         (*methods[i].func)(session, args_in, data->args_out, data);
     2213      evbuffer_free (buf);
     2214
     2215      tr_variantFree (&response);
     2216    }
     2217  else if (methods[i].immediate)
     2218    {
     2219      int64_t tag;
     2220      tr_variant response;
     2221      tr_variant * args_out;
     2222      struct evbuffer * buf;
     2223
     2224      tr_variantInitDict (&response, 3);
     2225      args_out = tr_variantDictAddDict (&response, TR_KEY_arguments, 0);
     2226      result = (*methods[i].func)(session, args_in, args_out, NULL);
     2227      if (result == NULL)
     2228        result = "success";
     2229      tr_variantDictAddStr (&response, TR_KEY_result, result);
     2230      if (tr_variantDictFindInt (request, TR_KEY_tag, &tag))
     2231        tr_variantDictAddInt (&response, TR_KEY_tag, tag);
     2232
     2233      buf = tr_variantToBuf (&response, TR_VARIANT_FMT_JSON_LEAN);
     2234      (*callback)(session, buf, callback_user_data);
     2235      evbuffer_free (buf);
     2236
     2237      tr_variantFree (&response);
     2238    }
     2239  else
     2240    {
     2241      int64_t tag;
     2242      struct tr_rpc_idle_data * data = tr_new0 (struct tr_rpc_idle_data, 1);
     2243      data->session = session;
     2244      data->response = tr_new0 (tr_variant, 1);
     2245      tr_variantInitDict (data->response, 3);
     2246      if (tr_variantDictFindInt (request, TR_KEY_tag, &tag))
     2247        tr_variantDictAddInt (data->response, TR_KEY_tag, tag);
     2248      data->args_out = tr_variantDictAddDict (data->response, TR_KEY_arguments, 0);
     2249      data->callback = callback;
     2250      data->callback_user_data = callback_user_data;
     2251      (*methods[i].func)(session, args_in, data->args_out, data);
    21312252    }
    21322253}
     
    21392260                          void                  * callback_user_data)
    21402261{
    2141     tr_variant top;
    2142     int have_content;
    2143 
    2144     if (request_len < 0)
    2145         request_len = strlen (request_json);
    2146 
    2147     have_content = !tr_variantFromJson (&top, request_json, request_len);
    2148     request_exec (session, have_content ? &top : NULL, callback, callback_user_data);
    2149 
    2150     if (have_content)
    2151         tr_variantFree (&top);
     2262  tr_variant top;
     2263  int have_content;
     2264
     2265  if (request_len < 0)
     2266    request_len = strlen (request_json);
     2267
     2268  have_content = !tr_variantFromJson (&top, request_json, request_len);
     2269  request_exec (session, have_content ? &top : NULL, callback, callback_user_data);
     2270
     2271  if (have_content)
     2272    tr_variantFree (&top);
    21522273}
    21532274
     
    21672288
    21682289{
    2169     int valueCount;
    2170     int * values = tr_parseNumberRange (str, len, &valueCount);
    2171 
    2172     if (valueCount == 0)
    2173         tr_variantInitStr (setme, str, len);
    2174     else if (valueCount == 1)
    2175         tr_variantInitInt (setme, values[0]);
    2176     else {
    2177         int i;
    2178         tr_variantInitList (setme, valueCount);
    2179         for (i=0; i<valueCount; ++i)
    2180             tr_variantListAddInt (setme, values[i]);
    2181     }
    2182 
    2183     tr_free (values);
     2290  int valueCount;
     2291  int * values = tr_parseNumberRange (str, len, &valueCount);
     2292
     2293  if (valueCount == 0)
     2294    {
     2295      tr_variantInitStr (setme, str, len);
     2296    }
     2297  else if (valueCount == 1)
     2298    {
     2299      tr_variantInitInt (setme, values[0]);
     2300    }
     2301  else
     2302    {
     2303      int i;
     2304
     2305      tr_variantInitList (setme, valueCount);
     2306
     2307      for (i=0; i<valueCount; ++i)
     2308        tr_variantListAddInt (setme, values[i]);
     2309    }
     2310
     2311  tr_free (values);
    21842312}
    21852313
     
    21912319                         void                 * callback_user_data)
    21922320{
    2193     tr_variant      top, * args;
    2194     char *       request = tr_strndup (request_uri, request_len);
    2195     const char * pch;
    2196 
    2197     tr_variantInitDict (&top, 3);
    2198     args = tr_variantDictAddDict (&top, TR_KEY_arguments, 0);
    2199 
    2200     pch = strchr (request, '?');
    2201     if (!pch) pch = request;
    2202     while (pch)
    2203     {
    2204         const char * delim = strchr (pch, '=');
    2205         const char * next = strchr (pch, '&');
    2206         if (delim)
    2207         {
    2208             char *    key = tr_strndup (pch, delim - pch);
    2209             int       isArg = strcmp (key, "method") && strcmp (key, "tag");
    2210             tr_variant * parent = isArg ? args : &top;
    2211             tr_rpc_parse_list_str (tr_variantDictAdd (parent, tr_quark_new (key, delim-pch)),
    2212                                   delim + 1,
    2213                                   next ? (size_t)(
    2214                                        next -
    2215                                     (delim + 1)) : strlen (delim + 1));
    2216             tr_free (key);
    2217         }
    2218         pch = next ? next + 1 : NULL;
    2219     }
    2220 
    2221     request_exec (session, &top, callback, callback_user_data);
    2222 
    2223     /* cleanup */
    2224     tr_variantFree (&top);
    2225     tr_free (request);
    2226 }
     2321  const char * pch;
     2322  tr_variant top;
     2323  tr_variant * args;
     2324  char * request = tr_strndup (request_uri, request_len);
     2325
     2326  tr_variantInitDict (&top, 3);
     2327  args = tr_variantDictAddDict (&top, TR_KEY_arguments, 0);
     2328
     2329  pch = strchr (request, '?');
     2330  if (!pch) pch = request;
     2331  while (pch)
     2332    {
     2333      const char * delim = strchr (pch, '=');
     2334      const char * next = strchr (pch, '&');
     2335      if (delim)
     2336        {
     2337          char * key = tr_strndup (pch, delim - pch);
     2338          int isArg = strcmp (key, "method") && strcmp (key, "tag");
     2339          tr_variant * parent = isArg ? args : &top;
     2340
     2341          tr_rpc_parse_list_str (tr_variantDictAdd (parent, tr_quark_new (key, delim-pch)),
     2342                                 delim + 1,
     2343                                 next ? (size_t)(next - (delim + 1)) : strlen (delim + 1));
     2344          tr_free (key);
     2345        }
     2346
     2347      pch = next ? next + 1 : NULL;
     2348    }
     2349
     2350  request_exec (session, &top, callback, callback_user_data);
     2351
     2352  /* cleanup */
     2353  tr_variantFree (&top);
     2354  tr_free (request);
     2355}
  • trunk/libtransmission/torrent.c

    r14078 r14079  
    7575tr_torrentName (const tr_torrent * tor)
    7676{
    77     return tor ? tor->info.name : "";
     77  return tor ? tor->info.name : "";
    7878}
    7979
     
    8181tr_torrentId (const tr_torrent * tor)
    8282{
    83     return tor ? tor->uniqueId : -1;
     83  return tor ? tor->uniqueId : -1;
    8484}
    8585
     
    8787tr_torrentFindFromId (tr_session * session, int id)
    8888{
    89     tr_torrent * tor = NULL;
    90 
    91     while ((tor = tr_torrentNext (session, tor)))
    92         if (tor->uniqueId == id)
    93             return tor;
    94 
    95     return NULL;
     89  tr_torrent * tor = NULL;
     90
     91  while ((tor = tr_torrentNext (session, tor)))
     92    if (tor->uniqueId == id)
     93      return tor;
     94
     95  return NULL;
    9696}
    9797
     
    9999tr_torrentFindFromHashString (tr_session *  session, const char * str)
    100100{
    101     tr_torrent * tor = NULL;
    102 
    103     while ((tor = tr_torrentNext (session, tor)))
    104         if (!evutil_ascii_strcasecmp (str, tor->info.hashString))
    105             return tor;
    106 
    107     return NULL;
     101  tr_torrent * tor = NULL;
     102
     103  while ((tor = tr_torrentNext (session, tor)))
     104    if (!evutil_ascii_strcasecmp (str, tor->info.hashString))
     105      return tor;
     106
     107  return NULL;
    108108}
    109109
     
    111111tr_torrentFindFromHash (tr_session * session, const uint8_t * torrentHash)
    112112{
    113     tr_torrent * tor = NULL;
    114 
    115     while ((tor = tr_torrentNext (session, tor)))
    116         if (*tor->info.hash == *torrentHash)
    117             if (!memcmp (tor->info.hash, torrentHash, SHA_DIGEST_LENGTH))
    118                 return tor;
    119 
    120     return NULL;
     113  tr_torrent * tor = NULL;
     114
     115  while ((tor = tr_torrentNext (session, tor)))
     116    if (*tor->info.hash == *torrentHash)
     117      if (!memcmp (tor->info.hash, torrentHash, SHA_DIGEST_LENGTH))
     118        return tor;
     119
     120  return NULL;
    121121}
    122122
     
    124124tr_torrentFindFromMagnetLink (tr_session * session, const char * magnet)
    125125{
    126     tr_magnet_info * info;
    127     tr_torrent * tor = NULL;
    128 
    129     if ((info = tr_magnetParse (magnet)))
    130     {
    131         tor = tr_torrentFindFromHash (session, info->hash);
    132         tr_magnetFree (info);
    133     }
    134 
    135     return tor;
     126  tr_magnet_info * info;
     127  tr_torrent * tor = NULL;
     128
     129  if ((info = tr_magnetParse (magnet)))
     130    {
     131      tor = tr_torrentFindFromHash (session, info->hash);
     132      tr_magnetFree (info);
     133    }
     134
     135  return tor;
    136136}
    137137
     
    140140                                  const uint8_t * obfuscatedTorrentHash)
    141141{
    142     tr_torrent * tor = NULL;
    143 
    144     while ((tor = tr_torrentNext (session, tor)))
    145         if (!memcmp (tor->obfuscatedHash, obfuscatedTorrentHash,
    146                      SHA_DIGEST_LENGTH))
    147             return tor;
    148 
    149     return NULL;
     142  tr_torrent * tor = NULL;
     143
     144  while ((tor = tr_torrentNext (session, tor)))
     145    if (!memcmp (tor->obfuscatedHash, obfuscatedTorrentHash, SHA_DIGEST_LENGTH))
     146      return tor;
     147
     148  return NULL;
    150149}
    151150
     
    224223tr_torrentSetSpeedLimit_Bps (tr_torrent * tor, tr_direction dir, unsigned int Bps)
    225224{
    226     assert (tr_isTorrent (tor));
    227     assert (tr_isDirection (dir));
    228 
    229     if (tr_bandwidthSetDesiredSpeed_Bps (&tor->bandwidth, dir, Bps))
    230         tr_torrentSetDirty (tor);
     225  assert (tr_isTorrent (tor));
     226  assert (tr_isDirection (dir));
     227
     228  if (tr_bandwidthSetDesiredSpeed_Bps (&tor->bandwidth, dir, Bps))
     229    tr_torrentSetDirty (tor);
    231230}
    232231void
    233232tr_torrentSetSpeedLimit_KBps (tr_torrent * tor, tr_direction dir, unsigned int KBps)
    234233{
    235     tr_torrentSetSpeedLimit_Bps (tor, dir, toSpeedBytes (KBps));
     234  tr_torrentSetSpeedLimit_Bps (tor, dir, toSpeedBytes (KBps));
    236235}
    237236
     
    239238tr_torrentGetSpeedLimit_Bps (const tr_torrent * tor, tr_direction dir)
    240239{
    241     assert (tr_isTorrent (tor));
    242     assert (tr_isDirection (dir));
    243 
    244     return tr_bandwidthGetDesiredSpeed_Bps (&tor->bandwidth, dir);
     240  assert (tr_isTorrent (tor));
     241  assert (tr_isDirection (dir));
     242
     243  return tr_bandwidthGetDesiredSpeed_Bps (&tor->bandwidth, dir);
    245244}
    246245unsigned int
     
    398397tr_torrentIsSeedRatioDone (const tr_torrent * tor)
    399398{
    400     uint64_t bytesLeft;
    401     return tr_torrentGetSeedRatioBytes (tor, &bytesLeft, NULL) && !bytesLeft;
     399  uint64_t bytesLeft;
     400  return tr_torrentGetSeedRatioBytes (tor, &bytesLeft, NULL) && !bytesLeft;
    402401}
    403402
     
    409408tr_torrentSetIdleMode (tr_torrent *  tor, tr_idlelimit mode)
    410409{
    411     assert (tr_isTorrent (tor));
    412     assert (mode==TR_IDLELIMIT_GLOBAL || mode==TR_IDLELIMIT_SINGLE || mode==TR_IDLELIMIT_UNLIMITED);
    413 
    414     if (mode != tor->idleLimitMode)
    415     {
    416         tor->idleLimitMode = mode;
    417 
    418         tr_torrentSetDirty (tor);
     410  assert (tr_isTorrent (tor));
     411  assert (mode==TR_IDLELIMIT_GLOBAL || mode==TR_IDLELIMIT_SINGLE || mode==TR_IDLELIMIT_UNLIMITED);
     412
     413  if (mode != tor->idleLimitMode)
     414    {
     415      tor->idleLimitMode = mode;
     416
     417      tr_torrentSetDirty (tor);
    419418    }
    420419}
     
    423422tr_torrentGetIdleMode (const tr_torrent * tor)
    424423{
    425     assert (tr_isTorrent (tor));
    426 
    427     return tor->idleLimitMode;
     424  assert (tr_isTorrent (tor));
     425
     426  return tor->idleLimitMode;
    428427}
    429428
     
    431430tr_torrentSetIdleLimit (tr_torrent * tor, uint16_t idleMinutes)
    432431{
    433     assert (tr_isTorrent (tor));
    434 
    435     if (idleMinutes > 0)
    436     {
    437         tor->idleLimitMinutes = idleMinutes;
    438 
    439         tr_torrentSetDirty (tor);
     432  assert (tr_isTorrent (tor));
     433
     434  if (idleMinutes > 0)
     435    {
     436      tor->idleLimitMinutes = idleMinutes;
     437
     438      tr_torrentSetDirty (tor);
    440439    }
    441440}
     
    444443tr_torrentGetIdleLimit (const tr_torrent * tor)
    445444{
    446     assert (tr_isTorrent (tor));
    447 
    448     return tor->idleLimitMinutes;
     445  assert (tr_isTorrent (tor));
     446
     447  return tor->idleLimitMinutes;
    449448}
    450449
     
    452451tr_torrentGetSeedIdle (const tr_torrent * tor, uint16_t * idleMinutes)
    453452{
    454     bool isLimited;
    455 
    456     switch (tr_torrentGetIdleMode (tor))
    457     {
    458         case TR_IDLELIMIT_SINGLE:
    459             isLimited = true;
    460             if (idleMinutes)
    461                 *idleMinutes = tr_torrentGetIdleLimit (tor);
    462             break;
    463 
    464         case TR_IDLELIMIT_GLOBAL:
    465             isLimited = tr_sessionIsIdleLimited (tor->session);
    466             if (isLimited && idleMinutes)
    467                 *idleMinutes = tr_sessionGetIdleLimit (tor->session);
    468             break;
    469 
    470         default: /* TR_IDLELIMIT_UNLIMITED */
    471             isLimited = false;
    472             break;
    473     }
    474 
    475     return isLimited;
     453  bool isLimited;
     454
     455  switch (tr_torrentGetIdleMode (tor))
     456    {
     457      case TR_IDLELIMIT_SINGLE:
     458        isLimited = true;
     459        if (idleMinutes != NULL)
     460          *idleMinutes = tr_torrentGetIdleLimit (tor);
     461        break;
     462
     463      case TR_IDLELIMIT_GLOBAL:
     464        isLimited = tr_sessionIsIdleLimited (tor->session);
     465        if (isLimited && idleMinutes)
     466          *idleMinutes = tr_sessionGetIdleLimit (tor->session);
     467        break;
     468
     469      default: /* TR_IDLELIMIT_UNLIMITED */
     470        isLimited = false;
     471        break;
     472    }
     473
     474  return isLimited;
    476475}
    477476
     
    479478tr_torrentIsSeedIdleLimitDone (tr_torrent * tor)
    480479{
    481     uint16_t idleMinutes;
    482     return tr_torrentGetSeedIdle (tor, &idleMinutes)
    483         && difftime (tr_time (), MAX (tor->startDate, tor->activityDate)) >= idleMinutes * 60u;
     480  uint16_t idleMinutes;
     481  return tr_torrentGetSeedIdle (tor, &idleMinutes)
     482    && difftime (tr_time (), MAX (tor->startDate, tor->activityDate)) >= idleMinutes * 60u;
    484483}
    485484
     
    491490tr_torrentCheckSeedLimit (tr_torrent * tor)
    492491{
    493     assert (tr_isTorrent (tor));
    494 
    495     if (!tor->isRunning || tor->isStopping || !tr_torrentIsSeed (tor))
    496         return;
    497 
    498     /* if we're seeding and reach our seed ratio limit, stop the torrent */
    499     if (tr_torrentIsSeedRatioDone (tor))
    500     {
    501         tr_logAddTorInfo (tor, "%s", "Seed ratio reached; pausing torrent");
    502 
    503         tor->isStopping = true;
    504 
    505         /* maybe notify the client */
    506         if (tor->ratio_limit_hit_func != NULL)
    507             tor->ratio_limit_hit_func (tor, tor->ratio_limit_hit_func_user_data);
    508     }
    509     /* if we're seeding and reach our inactiviy limit, stop the torrent */
    510     else if (tr_torrentIsSeedIdleLimitDone (tor))
    511     {
    512         tr_logAddTorInfo (tor, "%s", "Seeding idle limit reached; pausing torrent");
    513 
    514         tor->isStopping = true;
    515         tor->finishedSeedingByIdle = true;
    516 
    517         /* maybe notify the client */
    518         if (tor->idle_limit_hit_func != NULL)
    519             tor->idle_limit_hit_func (tor, tor->idle_limit_hit_func_user_data);
     492  assert (tr_isTorrent (tor));
     493
     494  if (!tor->isRunning || tor->isStopping || !tr_torrentIsSeed (tor))
     495    return;
     496
     497  /* if we're seeding and reach our seed ratio limit, stop the torrent */
     498  if (tr_torrentIsSeedRatioDone (tor))
     499    {
     500      tr_logAddTorInfo (tor, "%s", "Seed ratio reached; pausing torrent");
     501
     502      tor->isStopping = true;
     503
     504      /* maybe notify the client */
     505      if (tor->ratio_limit_hit_func != NULL)
     506        tor->ratio_limit_hit_func (tor, tor->ratio_limit_hit_func_user_data);
     507    }
     508  /* if we're seeding and reach our inactiviy limit, stop the torrent */
     509  else if (tr_torrentIsSeedIdleLimitDone (tor))
     510    {
     511      tr_logAddTorInfo (tor, "%s", "Seeding idle limit reached; pausing torrent");
     512
     513      tor->isStopping = true;
     514      tor->finishedSeedingByIdle = true;
     515
     516      /* maybe notify the client */
     517      if (tor->idle_limit_hit_func != NULL)
     518        tor->idle_limit_hit_func (tor, tor->idle_limit_hit_func_user_data);
    520519    }
    521520}
     
    528527tr_torrentSetLocalError (tr_torrent * tor, const char * fmt, ...)
    529528{
    530     va_list ap;
    531 
    532     assert (tr_isTorrent (tor));
    533 
    534     va_start (ap, fmt);
    535     tor->error = TR_STAT_LOCAL_ERROR;
    536     tor->errorTracker[0] = '\0';
    537     evutil_vsnprintf (tor->errorString, sizeof (tor->errorString), fmt, ap);
    538     va_end (ap);
    539 
    540     tr_logAddTorErr (tor, "%s", tor->errorString);
    541 
    542     if (tor->isRunning)
    543         tor->isStopping = true;
     529  va_list ap;
     530
     531  assert (tr_isTorrent (tor));
     532
     533  va_start (ap, fmt);
     534  tor->error = TR_STAT_LOCAL_ERROR;
     535  tor->errorTracker[0] = '\0';
     536  evutil_vsnprintf (tor->errorString, sizeof (tor->errorString), fmt, ap);
     537  va_end (ap);
     538
     539  tr_logAddTorErr (tor, "%s", tor->errorString);
     540
     541  if (tor->isRunning)
     542    tor->isStopping = true;
    544543}
    545544
     
    547546tr_torrentClearError (tr_torrent * tor)
    548547{
    549     tor->error = TR_STAT_OK;
    550     tor->errorString[0] = '\0';
    551     tor->errorTracker[0] = '\0';
     548  tor->error = TR_STAT_OK;
     549  tor->errorString[0] = '\0';
     550  tor->errorTracker[0] = '\0';
    552551}
    553552
     
    555554onTrackerResponse (tr_torrent * tor, const tr_tracker_event * event, void * unused UNUSED)
    556555{
    557     switch (event->messageType)
    558     {
    559         case TR_TRACKER_PEERS:
     556  switch (event->messageType)
     557    {
     558      case TR_TRACKER_PEERS:
    560559        {
    561             size_t i;
    562             const int8_t seedProbability = event->seedProbability;
    563             const bool allAreSeeds = seedProbability == 100;
    564 
    565              if (allAreSeeds)
    566                 tr_logAddTorDbg (tor, "Got %zu seeds from tracker", event->pexCount);
    567             else
    568                 tr_logAddTorDbg (tor, "Got %zu peers from tracker", event->pexCount);
    569 
    570             for (i = 0; i < event->pexCount; ++i)
    571                 tr_peerMgrAddPex (tor, TR_PEER_FROM_TRACKER, &event->pex[i], seedProbability);
    572 
    573             break;
     560          size_t i;
     561          const int8_t seedProbability = event->seedProbability;
     562          const bool allAreSeeds = seedProbability == 100;
     563
     564          if (allAreSeeds)
     565            tr_logAddTorDbg (tor, "Got %zu seeds from tracker", event->pexCount);
     566          else
     567            tr_logAddTorDbg (tor, "Got %zu peers from tracker", event->pexCount);
     568
     569          for (i = 0; i < event->pexCount; ++i)
     570            tr_peerMgrAddPex (tor, TR_PEER_FROM_TRACKER, &event->pex[i], seedProbability);
     571
     572          break;
    574573        }
    575574
    576         case TR_TRACKER_WARNING:
    577             tr_logAddTorErr (tor, _("Tracker warning: \"%s\""), event->text);
    578             tor->error = TR_STAT_TRACKER_WARNING;
    579             tr_strlcpy (tor->errorTracker, event->tracker, sizeof (tor->errorTracker));
    580             tr_strlcpy (tor->errorString, event->text, sizeof (tor->errorString));
    581             break;
    582 
    583         case TR_TRACKER_ERROR:
    584             tr_logAddTorErr (tor, _("Tracker error: \"%s\""), event->text);
    585             tor->error = TR_STAT_TRACKER_ERROR;
    586             tr_strlcpy (tor->errorTracker, event->tracker, sizeof (tor->errorTracker));
    587             tr_strlcpy (tor->errorString, event->text, sizeof (tor->errorString));
    588             break;
    589 
    590         case TR_TRACKER_ERROR_CLEAR:
    591             if (tor->error != TR_STAT_LOCAL_ERROR)
    592                 tr_torrentClearError (tor);
    593             break;
     575      case TR_TRACKER_WARNING:
     576        tr_logAddTorErr (tor, _("Tracker warning: \"%s\""), event->text);
     577        tor->error = TR_STAT_TRACKER_WARNING;
     578        tr_strlcpy (tor->errorTracker, event->tracker, sizeof (tor->errorTracker));
     579        tr_strlcpy (tor->errorString, event->text, sizeof (tor->errorString));
     580        break;
     581
     582      case TR_TRACKER_ERROR:
     583        tr_logAddTorErr (tor, _("Tracker error: \"%s\""), event->text);
     584        tor->error = TR_STAT_TRACKER_ERROR;
     585        tr_strlcpy (tor->errorTracker, event->tracker, sizeof (tor->errorTracker));
     586        tr_strlcpy (tor->errorString, event->text, sizeof (tor->errorString));
     587        break;
     588
     589      case TR_TRACKER_ERROR_CLEAR:
     590        if (tor->error != TR_STAT_LOCAL_ERROR)
     591          tr_torrentClearError (tor);
     592        break;
    594593    }
    595594}
     
    604603getBytePiece (const tr_info * info, uint64_t byteOffset)
    605604{
    606     tr_piece_index_t piece;
    607 
    608     assert (info);
    609     assert (info->pieceSize != 0);
    610 
    611     piece = byteOffset / info->pieceSize;
    612 
    613     /* handle 0-byte files at the end of a torrent */
    614     if (byteOffset == info->totalSize)
    615       piece = info->pieceCount - 1;
    616 
    617     return piece;
     605  tr_piece_index_t piece;
     606
     607  assert (info);
     608  assert (info->pieceSize != 0);
     609
     610  piece = byteOffset / info->pieceSize;
     611
     612  /* handle 0-byte files at the end of a torrent */
     613  if (byteOffset == info->totalSize)
     614    piece = info->pieceCount - 1;
     615
     616  return piece;
    618617}
    619618
     
    622621                tr_file_index_t fileIndex)
    623622{
    624     tr_file * file;
    625     uint64_t  firstByte, lastByte;
    626 
    627     assert (info);
    628     assert (fileIndex < info->fileCount);
    629 
    630     file = &info->files[fileIndex];
    631     firstByte = file->offset;
    632     lastByte = firstByte + (file->length ? file->length - 1 : 0);
    633     file->firstPiece = getBytePiece (info, firstByte);
    634     file->lastPiece = getBytePiece (info, lastByte);
     623  tr_file * file;
     624  uint64_t  firstByte, lastByte;
     625
     626  assert (info);
     627  assert (fileIndex < info->fileCount);
     628
     629  file = &info->files[fileIndex];
     630  firstByte = file->offset;
     631  lastByte = firstByte + (file->length ? file->length - 1 : 0);
     632  file->firstPiece = getBytePiece (info, firstByte);
     633  file->lastPiece = getBytePiece (info, lastByte);
    635634}
    636635
     
    639638              const tr_file *  file)
    640639{
    641     return (file->firstPiece <= piece) && (piece <= file->lastPiece);
     640  return (file->firstPiece <= piece) && (piece <= file->lastPiece);
    642641}
    643642
     
    647646                        int                fileHint)
    648647{
    649     tr_file_index_t i;
    650     tr_priority_t priority = TR_PRI_LOW;
    651 
    652     /* find the first file that has data in this piece */
    653     if (fileHint >= 0) {
    654         i = fileHint;
    655         while (i > 0 && pieceHasFile (piece, &tor->info.files[i - 1]))
    656             --i;
    657     } else {
    658         for (i = 0; i < tor->info.fileCount; ++i)
    659             if (pieceHasFile (piece, &tor->info.files[i]))
    660                 break;
    661     }
    662 
    663     /* the piece's priority is the max of the priorities
    664      * of all the files in that piece */
    665     for (; i < tor->info.fileCount; ++i)
    666     {
    667         const tr_file * file = &tor->info.files[i];
    668 
    669         if (!pieceHasFile (piece, file))
    670             break;
    671 
    672         priority = MAX (priority, file->priority);
    673 
    674         /* when dealing with multimedia files, getting the first and
    675            last pieces can sometimes allow you to preview it a bit
    676            before it's fully downloaded... */
    677         if (file->priority >= TR_PRI_NORMAL)
    678             if (file->firstPiece == piece || file->lastPiece == piece)
    679                 priority = TR_PRI_HIGH;
    680     }
    681 
    682     return priority;
     648  tr_file_index_t i;
     649  tr_priority_t priority = TR_PRI_LOW;
     650
     651  /* find the first file that has data in this piece */
     652  if (fileHint >= 0)
     653    {
     654      i = fileHint;
     655      while (i > 0 && pieceHasFile (piece, &tor->info.files[i - 1]))
     656        --i;
     657    }
     658  else
     659    {
     660      for (i=0; i<tor->info.fileCount; ++i)
     661        if (pieceHasFile (piece, &tor->info.files[i]))
     662          break;
     663    }
     664
     665  /* the piece's priority is the max of the priorities
     666   * of all the files in that piece */
     667  for (; i<tor->info.fileCount; ++i)
     668    {
     669      const tr_file * file = &tor->info.files[i];
     670
     671      if (!pieceHasFile (piece, file))
     672        break;
     673
     674      priority = MAX (priority, file->priority);
     675
     676      /* when dealing with multimedia files, getting the first and
     677         last pieces can sometimes allow you to preview it a bit
     678         before it's fully downloaded... */
     679      if (file->priority >= TR_PRI_NORMAL)
     680        if (file->firstPiece == piece || file->lastPiece == piece)
     681          priority = TR_PRI_HIGH;
     682    }
     683
     684  return priority;
    683685}
    684686
     
    686688tr_torrentInitFilePieces (tr_torrent * tor)
    687689{
    688     int * firstFiles;
    689     tr_file_index_t f;
    690     tr_piece_index_t p;
    691     uint64_t offset = 0;
    692     tr_info * inf = &tor->info;
    693 
    694     /* assign the file offsets */
    695     for (f=0; f<inf->fileCount; ++f) {
    696         inf->files[f].offset = offset;
    697         offset += inf->files[f].length;
    698         initFilePieces (inf, f);
    699     }
    700 
    701     /* build the array of first-file hints to give calculatePiecePriority */
    702     firstFiles = tr_new (int, inf->pieceCount);
    703     for (p=f=0; p<inf->pieceCount; ++p) {
    704         while (inf->files[f].lastPiece < p)
    705             ++f;
    706         firstFiles[p] = f;
     690  int * firstFiles;
     691  tr_file_index_t f;
     692  tr_piece_index_t p;
     693  uint64_t offset = 0;
     694  tr_info * inf = &tor->info;
     695
     696  /* assign the file offsets */
     697  for (f=0; f<inf->fileCount; ++f)
     698    {
     699      inf->files[f].offset = offset;
     700      offset += inf->files[f].length;
     701      initFilePieces (inf, f);
     702    }
     703
     704  /* build the array of first-file hints to give calculatePiecePriority */
     705  firstFiles = tr_new (int, inf->pieceCount);
     706  for (p=f=0; p<inf->pieceCount; ++p)
     707    {
     708      while (inf->files[f].lastPiece < p)
     709        ++f;
     710      firstFiles[p] = f;
    707711    }
    708712
    709713#if 0
    710     /* test to confirm the first-file hints are correct */
    711     for (p=0; p<inf->pieceCount; ++p) {
    712         f = firstFiles[p];
    713         assert (inf->files[f].firstPiece <= p);
    714         assert (inf->files[f].lastPiece >= p);
    715         if (f > 0)
    716             assert (inf->files[f-1].lastPiece < p);
    717         for (f=0; f<inf->fileCount; ++f)
    718             if (pieceHasFile (p, &inf->files[f]))
    719                 break;
    720         assert ((int)f == firstFiles[p]);
     714  /* test to confirm the first-file hints are correct */
     715  for (p=0; p<inf->pieceCount; ++p)
     716    {
     717      f = firstFiles[p];
     718      assert (inf->files[f].firstPiece <= p);
     719      assert (inf->files[f].lastPiece >= p);
     720      if (f > 0)
     721        assert (inf->files[f-1].lastPiece < p);
     722
     723      for (f=0; f<inf->fileCount; ++f)
     724        if (pieceHasFile (p, &inf->files[f]))
     725          break;
     726
     727      assert ((int)f == firstFiles[p]);
    721728    }
    722729#endif
    723730
    724     for (p=0; p<inf->pieceCount; ++p)
    725         inf->pieces[p].priority = calculatePiecePriority (tor, p, firstFiles[p]);
    726 
    727     tr_free (firstFiles);
     731  for (p=0; p<inf->pieceCount; ++p)
     732    inf->pieces[p].priority = calculatePiecePriority (tor, p, firstFiles[p]);
     733
     734  tr_free (firstFiles);
    728735}
    729736
     
    738745tr_getBlockSize (uint32_t pieceSize)
    739746{
    740     uint32_t b = pieceSize;
    741 
    742     while (b > MAX_BLOCK_SIZE)
    743         b /= 2u;
    744 
    745     if (!b || (pieceSize % b)) /* not cleanly divisible */
    746         return 0;
    747     return b;
     747  uint32_t b = pieceSize;
     748
     749  while (b > MAX_BLOCK_SIZE)
     750    b /= 2u;
     751
     752  if (!b || (pieceSize % b)) /* not cleanly divisible */
     753    return 0;
     754
     755  return b;
    748756}
    749757
     
    753761torrentInitFromInfo (tr_torrent * tor)
    754762{
    755     uint64_t t;
    756     tr_info * info = &tor->info;
    757 
    758     tor->blockSize = tr_getBlockSize (info->pieceSize);
    759 
    760     if (info->pieceSize)
    761         tor->lastPieceSize = (uint32_t)(info->totalSize % info->pieceSize);
    762 
    763     if (!tor->lastPieceSize)
    764         tor->lastPieceSize = info->pieceSize;
    765 
    766     if (tor->blockSize)
    767         tor->lastBlockSize = info->totalSize % tor->blockSize;
    768 
    769     if (!tor->lastBlockSize)
    770         tor->lastBlockSize = tor->blockSize;
    771 
    772     tor->blockCount = tor->blockSize
    773         ? (info->totalSize + tor->blockSize - 1) / tor->blockSize
    774         : 0;
    775 
    776     tor->blockCountInPiece = tor->blockSize
    777         ? info->pieceSize / tor->blockSize
    778         : 0;
    779 
    780     tor->blockCountInLastPiece = tor->blockSize
    781         ? (tor->lastPieceSize + tor->blockSize - 1) / tor->blockSize
    782         : 0;
    783 
    784     /* check our work */
    785     if (tor->blockSize != 0)
    786         assert ((info->pieceSize % tor->blockSize) == 0);
    787     t = info->pieceCount - 1;
    788     t *= info->pieceSize;
    789     t += tor->lastPieceSize;
    790     assert (t == info->totalSize);
    791     t = tor->blockCount - 1;
    792     t *= tor->blockSize;
    793     t += tor->lastBlockSize;
    794     assert (t == info->totalSize);
    795     t = info->pieceCount - 1;
    796     t *= tor->blockCountInPiece;
    797     t += tor->blockCountInLastPiece;
    798     assert (t == (uint64_t)tor->blockCount);
    799 
    800     tr_cpConstruct (&tor->completion, tor);
    801 
    802     tr_torrentInitFilePieces (tor);
    803 
    804     tor->completeness = tr_cpGetStatus (&tor->completion);
     763  uint64_t t;
     764  tr_info * info = &tor->info;
     765
     766  tor->blockSize = tr_getBlockSize (info->pieceSize);
     767
     768  if (info->pieceSize)
     769    tor->lastPieceSize = (uint32_t)(info->totalSize % info->pieceSize);
     770
     771  if (!tor->lastPieceSize)
     772    tor->lastPieceSize = info->pieceSize;
     773
     774  if (tor->blockSize)
     775    tor->lastBlockSize = info->totalSize % tor->blockSize;
     776
     777  if (!tor->lastBlockSize)
     778    tor->lastBlockSize = tor->blockSize;
     779
     780  tor->blockCount = tor->blockSize
     781    ? (info->totalSize + tor->blockSize - 1) / tor->blockSize
     782    : 0;
     783
     784  tor->blockCountInPiece = tor->blockSize
     785    ? info->pieceSize / tor->blockSize
     786    : 0;
     787
     788  tor->blockCountInLastPiece = tor->blockSize
     789    ? (tor->lastPieceSize + tor->blockSize - 1) / tor->blockSize
     790    : 0;
     791
     792  /* check our work */
     793  if (tor->blockSize != 0)
     794    assert ((info->pieceSize % tor->blockSize) == 0);
     795  t = info->pieceCount - 1;
     796  t *= info->pieceSize;
     797  t += tor->lastPieceSize;
     798  assert (t == info->totalSize);
     799  t = tor->blockCount - 1;
     800  t *= tor->blockSize;
     801  t += tor->lastBlockSize;
     802  assert (t == info->totalSize);
     803  t = info->pieceCount - 1;
     804  t *= tor->blockCountInPiece;
     805  t += tor->blockCountInLastPiece;
     806  assert (t == (uint64_t)tor->blockCount);
     807
     808  tr_cpConstruct (&tor->completion, tor);
     809
     810  tr_torrentInitFilePieces (tor);
     811
     812  tor->completeness = tr_cpGetStatus (&tor->completion);
    805813}
    806814
     
    810818tr_torrentGotNewInfoDict (tr_torrent * tor)
    811819{
    812     torrentInitFromInfo (tor);
    813 
    814     tr_peerMgrOnTorrentGotMetainfo (tor);
    815 
    816     tr_torrentFireMetadataCompleted (tor);
     820  torrentInitFromInfo (tor);
     821
     822  tr_peerMgrOnTorrentGotMetainfo (tor);
     823
     824  tr_torrentFireMetadataCompleted (tor);
    817825}
    818826
     
    820828hasAnyLocalData (const tr_torrent * tor)
    821829{
    822     tr_file_index_t i;
    823 
    824     for (i=0; i<tor->info.fileCount; ++i)
    825         if (tr_torrentFindFile2 (tor, i, NULL, NULL, NULL))
    826             return true;
    827 
    828     return false;
     830  tr_file_index_t i;
     831
     832  for (i=0; i<tor->info.fileCount; ++i)
     833    if (tr_torrentFindFile2 (tor, i, NULL, NULL, NULL))
     834      return true;
     835
     836  return false;
    829837}
    830838
     
    832840setLocalErrorIfFilesDisappeared (tr_torrent * tor)
    833841{
    834     const bool disappeared = (tr_cpHaveTotal (&tor->completion) > 0) && !hasAnyLocalData (tor);
    835 
    836     if (disappeared)
    837     {
    838         tr_deeplog_tor (tor, "%s", "[LAZY] uh oh, the files disappeared");
    839         tr_torrentSetLocalError (tor, "%s", _("No data found! Ensure your drives are connected or use \"Set Location\". To re-download, remove the torrent and re-add it."));
    840     }
    841 
    842     return disappeared;
     842  const bool disappeared = (tr_cpHaveTotal (&tor->completion) > 0) && !hasAnyLocalData (tor);
     843
     844  if (disappeared)
     845    {
     846      tr_deeplog_tor (tor, "%s", "[LAZY] uh oh, the files disappeared");
     847      tr_torrentSetLocalError (tor, "%s", _("No data found! Ensure your drives are connected or use \"Set Location\". To re-download, remove the torrent and re-add it."));
     848    }
     849
     850  return disappeared;
    843851}
    844852
     
    846854torrentInit (tr_torrent * tor, const tr_ctor * ctor)
    847855{
    848     int doStart;
    849     uint64_t loaded;
    850     const char * dir;
    851     bool isNewTorrent;
    852     struct stat st;
    853     static int nextUniqueId = 1;
    854     tr_session * session = tr_ctorGetSession (ctor);
    855 
    856     assert (session != NULL);
    857 
    858     tr_sessionLock (session);
    859 
    860     tor->session   = session;
    861     tor->uniqueId = nextUniqueId++;
    862     tor->magicNumber = TORRENT_MAGIC_NUMBER;
    863     tor->queuePosition = session->torrentCount;
    864 
    865     tr_sha1 (tor->obfuscatedHash, "req2", 4,
    866              tor->info.hash, SHA_DIGEST_LENGTH,
    867              NULL);
    868 
    869     if (!tr_ctorGetDownloadDir (ctor, TR_FORCE, &dir) ||
    870         !tr_ctorGetDownloadDir (ctor, TR_FALLBACK, &dir))
    871             tor->downloadDir = tr_strdup (dir);
    872 
    873     if (tr_ctorGetIncompleteDir (ctor, &dir))
    874         dir = tr_sessionGetIncompleteDir (session);
    875     if (tr_sessionIsIncompleteDirEnabled (session))
    876         tor->incompleteDir = tr_strdup (dir);
    877 
    878     tr_bandwidthConstruct (&tor->bandwidth, session, &session->bandwidth);
    879 
    880     tor->bandwidth.priority = tr_ctorGetBandwidthPriority (ctor);
    881 
    882     tor->error = TR_STAT_OK;
    883 
    884     tor->finishedSeedingByIdle = false;
    885 
    886     tr_peerMgrAddTorrent (session->peerMgr, tor);
    887 
    888     assert (!tor->downloadedCur);
    889     assert (!tor->uploadedCur);
    890 
    891     tr_torrentSetAddedDate (tor, tr_time ()); /* this is a default value to be
    892                                                   overwritten by the resume file */
    893 
    894     torrentInitFromInfo (tor);
    895     loaded = tr_torrentLoadResume (tor, ~0, ctor);
    896     tor->completeness = tr_cpGetStatus (&tor->completion);
    897     setLocalErrorIfFilesDisappeared (tor);
    898 
    899     tr_ctorInitTorrentPriorities (ctor, tor);
    900     tr_ctorInitTorrentWanted (ctor, tor);
    901 
    902     refreshCurrentDir (tor);
    903 
    904     doStart = tor->isRunning;
    905     tor->isRunning = 0;
    906 
    907     if (! (loaded & TR_FR_SPEEDLIMIT))
    908     {
    909         tr_torrentUseSpeedLimit (tor, TR_UP, false);
    910         tr_torrentSetSpeedLimit_Bps (tor, TR_UP, tr_sessionGetSpeedLimit_Bps (tor->session, TR_UP));
    911         tr_torrentUseSpeedLimit (tor, TR_DOWN, false);
    912         tr_torrentSetSpeedLimit_Bps (tor, TR_DOWN, tr_sessionGetSpeedLimit_Bps (tor->session, TR_DOWN));
    913         tr_torrentUseSessionLimits (tor, true);
    914     }
    915 
    916     if (! (loaded & TR_FR_RATIOLIMIT))
    917     {
    918         tr_torrentSetRatioMode (tor, TR_RATIOLIMIT_GLOBAL);
    919         tr_torrentSetRatioLimit (tor, tr_sessionGetRatioLimit (tor->session));
    920     }
    921 
    922     if (! (loaded & TR_FR_IDLELIMIT))
    923     {
    924         tr_torrentSetIdleMode (tor, TR_IDLELIMIT_GLOBAL);
    925         tr_torrentSetIdleLimit (tor, tr_sessionGetIdleLimit (tor->session));
    926     }
    927 
    928     /* add the torrent to tr_session.torrentList */
    929     session->torrentCount++;
    930     if (session->torrentList == NULL)
    931         session->torrentList = tor;
    932     else {
    933         tr_torrent * it = session->torrentList;
    934         while (it->next != NULL)
    935             it = it->next;
    936         it->next = tor;
    937     }
    938 
    939     /* if we don't have a local .torrent file already, assume the torrent is new */
    940     isNewTorrent = stat (tor->info.torrent, &st);
    941 
    942     /* maybe save our own copy of the metainfo */
    943     if (tr_ctorGetSave (ctor))
    944     {
    945         const tr_variant * val;
    946         if (!tr_ctorGetMetainfo (ctor, &val))
     856  int doStart;
     857  uint64_t loaded;
     858  const char * dir;
     859  bool isNewTorrent;
     860  struct stat st;
     861  tr_session * session = tr_ctorGetSession (ctor);
     862  static int nextUniqueId = 1;
     863
     864  assert (session != NULL);
     865
     866  tr_sessionLock (session);
     867
     868  tor->session   = session;
     869  tor->uniqueId = nextUniqueId++;
     870  tor->magicNumber = TORRENT_MAGIC_NUMBER;
     871  tor->queuePosition = session->torrentCount;
     872
     873  tr_sha1 (tor->obfuscatedHash, "req2", 4,
     874           tor->info.hash, SHA_DIGEST_LENGTH,
     875           NULL);
     876
     877  if (!tr_ctorGetDownloadDir (ctor, TR_FORCE, &dir) ||
     878    !tr_ctorGetDownloadDir (ctor, TR_FALLBACK, &dir))
     879      tor->downloadDir = tr_strdup (dir);
     880
     881  if (tr_ctorGetIncompleteDir (ctor, &dir))
     882    dir = tr_sessionGetIncompleteDir (session);
     883  if (tr_sessionIsIncompleteDirEnabled (session))
     884    tor->incompleteDir = tr_strdup (dir);
     885
     886  tr_bandwidthConstruct (&tor->bandwidth, session, &session->bandwidth);
     887
     888  tor->bandwidth.priority = tr_ctorGetBandwidthPriority (ctor);
     889
     890  tor->error = TR_STAT_OK;
     891
     892  tor->finishedSeedingByIdle = false;
     893
     894  tr_peerMgrAddTorrent (session->peerMgr, tor);
     895
     896  assert (!tor->downloadedCur);
     897  assert (!tor->uploadedCur);
     898
     899  tr_torrentSetAddedDate (tor, tr_time ()); /* this is a default value to be
     900                                               overwritten by the resume file */
     901
     902  torrentInitFromInfo (tor);
     903  loaded = tr_torrentLoadResume (tor, ~0, ctor);
     904  tor->completeness = tr_cpGetStatus (&tor->completion);
     905  setLocalErrorIfFilesDisappeared (tor);
     906
     907  tr_ctorInitTorrentPriorities (ctor, tor);
     908  tr_ctorInitTorrentWanted (ctor, tor);
     909
     910  refreshCurrentDir (tor);
     911
     912  doStart = tor->isRunning;
     913  tor->isRunning = 0;
     914
     915  if (!(loaded & TR_FR_SPEEDLIMIT))
     916    {
     917      tr_torrentUseSpeedLimit (tor, TR_UP, false);
     918      tr_torrentSetSpeedLimit_Bps (tor, TR_UP, tr_sessionGetSpeedLimit_Bps (tor->session, TR_UP));
     919      tr_torrentUseSpeedLimit (tor, TR_DOWN, false);
     920      tr_torrentSetSpeedLimit_Bps (tor, TR_DOWN, tr_sessionGetSpeedLimit_Bps (tor->session, TR_DOWN));
     921      tr_torrentUseSessionLimits (tor, true);
     922    }
     923
     924  if (!(loaded & TR_FR_RATIOLIMIT))
     925    {
     926      tr_torrentSetRatioMode (tor, TR_RATIOLIMIT_GLOBAL);
     927      tr_torrentSetRatioLimit (tor, tr_sessionGetRatioLimit (tor->session));
     928    }
     929
     930  if (!(loaded & TR_FR_IDLELIMIT))
     931    {
     932      tr_torrentSetIdleMode (tor, TR_IDLELIMIT_GLOBAL);
     933      tr_torrentSetIdleLimit (tor, tr_sessionGetIdleLimit (tor->session));
     934    }
     935
     936  /* add the torrent to tr_session.torrentList */
     937  session->torrentCount++;
     938  if (session->torrentList == NULL)
     939    {
     940      session->torrentList = tor;
     941    }
     942  else
     943    {
     944      tr_torrent * it = session->torrentList;
     945      while (it->next != NULL)
     946        it = it->next;
     947      it->next = tor;
     948    }
     949
     950  /* if we don't have a local .torrent file already, assume the torrent is new */
     951  isNewTorrent = stat (tor->info.torrent, &st);
     952
     953  /* maybe save our own copy of the metainfo */
     954  if (tr_ctorGetSave (ctor))
     955    {
     956      const tr_variant * val;
     957      if (!tr_ctorGetMetainfo (ctor, &val))
    947958        {
    948             const char * path = tor->info.torrent;
    949             const int err = tr_variantToFile (val, TR_VARIANT_FMT_BENC, path);
    950             if (err)
    951                 tr_torrentSetLocalError (tor, "Unable to save torrent file: %s", tr_strerror (err));
    952             tr_sessionSetTorrentFile (tor->session, tor->info.hashString, path);
     959          const char * path = tor->info.torrent;
     960          const int err = tr_variantToFile (val, TR_VARIANT_FMT_BENC, path);
     961          if (err)
     962            tr_torrentSetLocalError (tor, "Unable to save torrent file: %s", tr_strerror (err));
     963          tr_sessionSetTorrentFile (tor->session, tor->info.hashString, path);
    953964        }
    954965    }
    955966
    956     tor->tiers = tr_announcerAddTorrent (tor, onTrackerResponse, NULL);
    957 
    958     if (isNewTorrent)
    959     {
    960         tor->startAfterVerify = doStart;
    961         tr_torrentVerify (tor, NULL, NULL);
    962     }
    963     else if (doStart)
    964     {
    965         tr_torrentStart (tor);
    966     }
    967 
    968     tr_sessionUnlock (session);
     967  tor->tiers = tr_announcerAddTorrent (tor, onTrackerResponse, NULL);
     968
     969  if (isNewTorrent)
     970    {
     971      tor->startAfterVerify = doStart;
     972      tr_torrentVerify (tor, NULL, NULL);
     973    }
     974  else if (doStart)
     975    {
     976      tr_torrentStart (tor);
     977    }
     978
     979  tr_sessionUnlock (session);
    969980}
    970981
     
    976987                  int            * setme_duplicate_id)
    977988{
    978     bool doFree;
    979     bool didParse;
    980     bool hasInfo = false;
    981     tr_info tmp;
    982     const tr_variant * metainfo;
    983     tr_session * session = tr_ctorGetSession (ctor);
    984     tr_parse_result result = TR_PARSE_OK;
    985 
    986     if (setmeInfo == NULL)
    987         setmeInfo = &tmp;
    988     memset (setmeInfo, 0, sizeof (tr_info));
    989 
    990     if (tr_ctorGetMetainfo (ctor, &metainfo))
    991         return TR_PARSE_ERR;
    992 
    993     didParse = tr_metainfoParse (session, metainfo, setmeInfo,
    994                                  &hasInfo, dictLength);
    995     doFree = didParse && (setmeInfo == &tmp);
    996 
    997     if (!didParse)
    998         result = TR_PARSE_ERR;
    999 
    1000     if (didParse && hasInfo && !tr_getBlockSize (setmeInfo->pieceSize))
    1001         result = TR_PARSE_ERR;
    1002 
    1003     if (didParse && session && (result == TR_PARSE_OK))
    1004       {
    1005         const tr_torrent * const tor = tr_torrentFindFromHash (session, setmeInfo->hash);
    1006 
    1007         if (tor != NULL)
    1008           {
    1009             result = TR_PARSE_DUPLICATE;
    1010 
    1011             if (setme_duplicate_id != NULL)
    1012               *setme_duplicate_id = tr_torrentId (tor);
    1013           }
    1014       }
    1015 
    1016     if (doFree)
    1017         tr_metainfoFree (setmeInfo);
    1018 
    1019     if (setmeHasInfo != NULL)
    1020         *setmeHasInfo = hasInfo;
    1021 
    1022     return result;
     989  bool doFree;
     990  bool didParse;
     991  bool hasInfo = false;
     992  tr_info tmp;
     993  const tr_variant * metainfo;
     994  tr_session * session = tr_ctorGetSession (ctor);
     995  tr_parse_result result = TR_PARSE_OK;
     996
     997  if (setmeInfo == NULL)
     998    setmeInfo = &tmp;
     999  memset (setmeInfo, 0, sizeof (tr_info));
     1000
     1001  if (tr_ctorGetMetainfo (ctor, &metainfo))
     1002    return TR_PARSE_ERR;
     1003
     1004  didParse = tr_metainfoParse (session, metainfo, setmeInfo,
     1005                               &hasInfo, dictLength);
     1006  doFree = didParse && (setmeInfo == &tmp);
     1007
     1008  if (!didParse)
     1009    result = TR_PARSE_ERR;
     1010
     1011  if (didParse && hasInfo && !tr_getBlockSize (setmeInfo->pieceSize))
     1012    result = TR_PARSE_ERR;
     1013
     1014  if (didParse && session && (result == TR_PARSE_OK))
     1015    {
     1016      const tr_torrent * const tor = tr_torrentFindFromHash (session, setmeInfo->hash);
     1017
     1018      if (tor != NULL)
     1019        {
     1020          result = TR_PARSE_DUPLICATE;
     1021
     1022          if (setme_duplicate_id != NULL)
     1023            *setme_duplicate_id = tr_torrentId (tor);
     1024        }
     1025    }
     1026
     1027  if (doFree)
     1028    tr_metainfoFree (setmeInfo);
     1029
     1030  if (setmeHasInfo != NULL)
     1031    *setmeHasInfo = hasInfo;
     1032
     1033  return result;
    10231034}
    10241035
     
    10261037tr_torrentParse (const tr_ctor * ctor, tr_info * setmeInfo)
    10271038{
    1028     return torrentParseImpl (ctor, setmeInfo, NULL, NULL, NULL);
     1039  return torrentParseImpl (ctor, setmeInfo, NULL, NULL, NULL);
    10291040}
    10301041
     
    10521063      torrentInit (tor, ctor);
    10531064    }
    1054     else
     1065  else
    10551066    {
    10561067      if (r == TR_PARSE_DUPLICATE)
     
    10711082tr_torrentSetDownloadDir (tr_torrent * tor, const char * path)
    10721083{
    1073     assert (tr_isTorrent (tor));
    1074 
    1075     if (!path || !tor->downloadDir || strcmp (path, tor->downloadDir))
    1076     {
    1077         tr_free (tor->downloadDir);
    1078         tor->downloadDir = tr_strdup (path);
    1079         tr_torrentSetDirty (tor);
    1080     }
    1081 
    1082     refreshCurrentDir (tor);
     1084  assert (tr_isTorrent (tor));
     1085
     1086  if (!path || !tor->downloadDir || strcmp (path, tor->downloadDir))
     1087    {
     1088      tr_free (tor->downloadDir);
     1089      tor->downloadDir = tr_strdup (path);
     1090      tr_torrentSetDirty (tor);
     1091    }
     1092
     1093  refreshCurrentDir (tor);
    10831094}
    10841095
     
    10861097tr_torrentGetDownloadDir (const tr_torrent * tor)
    10871098{
    1088     assert (tr_isTorrent (tor));
    1089 
    1090     return tor->downloadDir;
     1099  assert (tr_isTorrent (tor));
     1100
     1101  return tor->downloadDir;
    10911102}
    10921103
     
    10941105tr_torrentGetCurrentDir (const tr_torrent * tor)
    10951106{
    1096     assert (tr_isTorrent (tor));
    1097 
    1098     return tor->currentDir;
     1107  assert (tr_isTorrent (tor));
     1108
     1109  return tor->currentDir;
    10991110}
    11001111
     
    11031114tr_torrentChangeMyPort (tr_torrent * tor)
    11041115{
    1105     assert (tr_isTorrent (tor));
    1106 
    1107     if (tor->isRunning)
    1108         tr_announcerChangeMyPort (tor);
     1116  assert (tr_isTorrent (tor));
     1117
     1118  if (tor->isRunning)
     1119    tr_announcerChangeMyPort (tor);
    11091120}
    11101121
     
    11121123tr_torrentManualUpdateImpl (void * vtor)
    11131124{
    1114     tr_torrent * tor = vtor;
    1115 
    1116     assert (tr_isTorrent (tor));
    1117 
    1118     if (tor->isRunning)
    1119         tr_announcerManualAnnounce (tor);
     1125  tr_torrent * tor = vtor;
     1126
     1127  assert (tr_isTorrent (tor));
     1128
     1129  if (tor->isRunning)
     1130    tr_announcerManualAnnounce (tor);
    11201131}
    11211132
     
    11231134tr_torrentManualUpdate (tr_torrent * tor)
    11241135{
    1125     assert (tr_isTorrent (tor));
    1126 
    1127     tr_runInEventThread (tor->session, tr_torrentManualUpdateImpl, tor);
     1136  assert (tr_isTorrent (tor));
     1137
     1138  tr_runInEventThread (tor->session, tr_torrentManualUpdateImpl, tor);
    11281139}
    11291140
     
    11311142tr_torrentCanManualUpdate (const tr_torrent * tor)
    11321143{
    1133     return (tr_isTorrent (tor))
    1134         && (tor->isRunning)
    1135         && (tr_announcerCanManualAnnounce (tor));
     1144  return (tr_isTorrent (tor))
     1145      && (tor->isRunning)
     1146      && (tr_announcerCanManualAnnounce (tor));
    11361147}
    11371148
     
    11391150tr_torrentInfo (const tr_torrent * tor)
    11401151{
    1141     return tr_isTorrent (tor) ? &tor->info : NULL;
     1152  return tr_isTorrent (tor) ? &tor->info : NULL;
    11421153}
    11431154
     
    11451156tr_torrentStatCached (tr_torrent * tor)
    11461157{
    1147     const time_t now = tr_time ();
    1148 
    1149     return tr_isTorrent (tor) && (now == tor->lastStatTime)
    1150          ? &tor->stats
    1151          : tr_torrentStat (tor);
     1158  const time_t now = tr_time ();
     1159
     1160  return tr_isTorrent (tor) && (now == tor->lastStatTime)
     1161       ? &tor->stats
     1162       : tr_torrentStat (tor);
    11521163}
    11531164
     
    11551166tr_torrentSetVerifyState (tr_torrent * tor, tr_verify_state state)
    11561167{
    1157     assert (tr_isTorrent (tor));
    1158     assert (state==TR_VERIFY_NONE || state==TR_VERIFY_WAIT || state==TR_VERIFY_NOW);
    1159 
    1160     tor->verifyState = state;
    1161     tor->anyDate = tr_time ();
     1168  assert (tr_isTorrent (tor));
     1169  assert (state==TR_VERIFY_NONE || state==TR_VERIFY_WAIT || state==TR_VERIFY_NOW);
     1170
     1171  tor->verifyState = state;
     1172  tor->anyDate = tr_time ();
    11621173}
    11631174
     
    11951206torrentGetIdleSecs (const tr_torrent * tor)
    11961207{
    1197     int idle_secs;
    1198     const tr_torrent_activity activity = tr_torrentGetActivity (tor);
    1199 
    1200     if ((activity == TR_STATUS_DOWNLOAD || activity == TR_STATUS_SEED) && tor->startDate != 0)
    1201         idle_secs = difftime (tr_time (), MAX (tor->startDate, tor->activityDate));
    1202     else
    1203         idle_secs = -1;
    1204 
    1205     return idle_secs;
     1208  int idle_secs;
     1209  const tr_torrent_activity activity = tr_torrentGetActivity (tor);
     1210
     1211  if ((activity == TR_STATUS_DOWNLOAD || activity == TR_STATUS_SEED) && tor->startDate != 0)
     1212    idle_secs = difftime (tr_time (), MAX (tor->startDate, tor->activityDate));
     1213  else
     1214    idle_secs = -1;
     1215
     1216  return idle_secs;
    12061217}
    12071218
     
    12091220tr_torrentIsStalled (const tr_torrent * tor)
    12101221{
    1211     return tr_sessionGetQueueStalledEnabled (tor->session)
    1212         && (torrentGetIdleSecs (tor) > (tr_sessionGetQueueStalledMinutes (tor->session) * 60));
     1222  return tr_sessionGetQueueStalledEnabled (tor->session)
     1223      && (torrentGetIdleSecs (tor) > (tr_sessionGetQueueStalledMinutes (tor->session) * 60));
    12131224}
    12141225
     
    13861397countFileBytesCompleted (const tr_torrent * tor, tr_file_index_t index)
    13871398{
    1388     uint64_t total = 0;
    1389     const tr_file * f = &tor->info.files[index];
    1390 
    1391     if (f->length)
    1392     {
    1393         tr_block_index_t first;
    1394         tr_block_index_t last;
    1395         tr_torGetFileBlockRange (tor, index, &first, &last);
    1396 
    1397         if (first == last)
     1399  uint64_t total = 0;
     1400  const tr_file * f = &tor->info.files[index];
     1401
     1402  if (f->length)
     1403    {
     1404      tr_block_index_t first;
     1405      tr_block_index_t last;
     1406      tr_torGetFileBlockRange (tor, index, &first, &last);
     1407
     1408      if (first == last)
    13981409        {
    1399             if (tr_cpBlockIsComplete (&tor->completion, first))
    1400                 total = f->length;
     1410          if (tr_cpBlockIsComplete (&tor->completion, first))
     1411            total = f->length;
    14011412        }
    1402         else
     1413      else
    14031414        {
    1404             /* the first block */
    1405             if (tr_cpBlockIsComplete (&tor->completion, first))
    1406                 total += tor->blockSize - (f->offset % tor->blockSize);
    1407 
    1408             /* the middle blocks */
    1409             if (first + 1 < last) {
    1410                 uint64_t u = tr_bitfieldCountRange (&tor->completion.blockBitfield, first+1, last);
    1411                 u *= tor->blockSize;
    1412                 total += u;
     1415          /* the first block */
     1416          if (tr_cpBlockIsComplete (&tor->completion, first))
     1417            total += tor->blockSize - (f->offset % tor->blockSize);
     1418
     1419          /* the middle blocks */
     1420          if (first + 1 < last)
     1421            {
     1422              uint64_t u = tr_bitfieldCountRange (&tor->completion.blockBitfield, first+1, last);
     1423              u *= tor->blockSize;
     1424              total += u;
    14131425            }
    14141426
    1415             /* the last block */
    1416             if (tr_cpBlockIsComplete (&tor->completion, last))
    1417                 total += (f->offset + f->length) - ((uint64_t)tor->blockSize * last);
     1427          /* the last block */
     1428          if (tr_cpBlockIsComplete (&tor->completion, last))
     1429            total += (f->offset + f->length) - ((uint64_t)tor->blockSize * last);
    14181430        }
    14191431    }
    14201432
    1421     return total;
     1433  return total;
    14221434}
    14231435
    14241436tr_file_stat *
    14251437tr_torrentFiles (const tr_torrent * tor,
    1426                  tr_file_index_t *  fileCount)
    1427 {
    1428     tr_file_index_t       i;
    1429     const tr_file_index_t n = tor->info.fileCount;
    1430     tr_file_stat *        files = tr_new0 (tr_file_stat, n);
    1431     tr_file_stat *        walk = files;
    1432     const bool            isSeed = tor->completeness == TR_SEED;
    1433 
    1434     assert (tr_isTorrent (tor));
    1435 
    1436     for (i=0; i<n; ++i, ++walk) {
    1437         const uint64_t b = isSeed ? tor->info.files[i].length : countFileBytesCompleted (tor, i);
    1438         walk->bytesCompleted = b;
    1439         walk->progress = tor->info.files[i].length > 0 ? ((float)b / tor->info.files[i].length) : 1.0f;
    1440     }
    1441 
    1442     if (fileCount)
    1443         *fileCount = n;
    1444 
    1445     return files;
    1446 }
    1447 
    1448 void
    1449 tr_torrentFilesFree (tr_file_stat *            files,
    1450                      tr_file_index_t fileCount UNUSED)
    1451 {
    1452     tr_free (files);
     1438                 tr_file_index_t  * fileCount)
     1439{
     1440  tr_file_index_t i;
     1441  const tr_file_index_t n = tor->info.fileCount;
     1442  tr_file_stat * files = tr_new0 (tr_file_stat, n);
     1443  tr_file_stat * walk = files;
     1444  const bool isSeed = tor->completeness == TR_SEED;
     1445
     1446  assert (tr_isTorrent (tor));
     1447
     1448  for (i=0; i<n; ++i, ++walk)
     1449    {
     1450      const uint64_t b = isSeed ? tor->info.files[i].length : countFileBytesCompleted (tor, i);
     1451      walk->bytesCompleted = b;
     1452      walk->progress = tor->info.files[i].length > 0 ? ((float)b / tor->info.files[i].length) : 1.0f;
     1453    }
     1454
     1455  if (fileCount != NULL)
     1456    *fileCount = n;
     1457
     1458  return files;
     1459}
     1460
     1461void
     1462tr_torrentFilesFree (tr_file_stat     * files,
     1463                     tr_file_index_t    fileCount UNUSED)
     1464{
     1465  tr_free (files);
    14531466}
    14541467
     
    15111524tr_torrentResetTransferStats (tr_torrent * tor)
    15121525{
    1513     tr_torrentLock (tor);
    1514 
    1515     tor->downloadedPrev += tor->downloadedCur;
    1516     tor->downloadedCur   = 0;
    1517     tor->uploadedPrev   += tor->uploadedCur;
    1518     tor->uploadedCur     = 0;
    1519     tor->corruptPrev    += tor->corruptCur;
    1520     tor->corruptCur      = 0;
    1521 
    1522     tr_torrentSetDirty (tor);
    1523 
    1524     tr_torrentUnlock (tor);
     1526  tr_torrentLock (tor);
     1527
     1528  tor->downloadedPrev += tor->downloadedCur;
     1529  tor->downloadedCur   = 0;
     1530  tor->uploadedPrev   += tor->uploadedCur;
     1531  tor->uploadedCur     = 0;
     1532  tor->corruptPrev    += tor->corruptCur;
     1533  tor->corruptCur      = 0;
     1534
     1535  tr_torrentSetDirty (tor);
     1536
     1537  tr_torrentUnlock (tor);
    15251538}
    15261539
     
    15301543                       bool             has)
    15311544{
    1532     assert (tr_isTorrent (tor));
    1533     assert (pieceIndex < tor->info.pieceCount);
    1534 
    1535     if (has)
    1536         tr_cpPieceAdd (&tor->completion, pieceIndex);
    1537     else
    1538         tr_cpPieceRem (&tor->completion, pieceIndex);
     1545  assert (tr_isTorrent (tor));
     1546  assert (pieceIndex < tor->info.pieceCount);
     1547
     1548  if (has)
     1549    tr_cpPieceAdd (&tor->completion, pieceIndex);
     1550  else
     1551    tr_cpPieceRem (&tor->completion, pieceIndex);
    15391552}
    15401553
     
    15501563freeTorrent (tr_torrent * tor)
    15511564{
    1552     tr_torrent * t;
    1553     tr_session *  session = tor->session;
    1554     tr_info *    inf = &tor->info;
    1555     const time_t now = tr_time ();
    1556 
    1557     assert (!tor->isRunning);
    1558 
    1559     tr_sessionLock (session);
    1560 
    1561     tr_peerMgrRemoveTorrent (tor);
    1562 
    1563     tr_announcerRemoveTorrent (session->announcer, tor);
    1564 
    1565     tr_cpDestruct (&tor->completion);
    1566 
    1567     tr_free (tor->downloadDir);
    1568     tr_free (tor->incompleteDir);
    1569 
    1570     if (tor == session->torrentList)
    1571         session->torrentList = tor->next;
    1572     else for (t = session->torrentList; t != NULL; t = t->next) {
    1573         if (t->next == tor) {
    1574             t->next = tor->next;
    1575             break;
     1565  tr_torrent * t;
     1566  tr_session * session = tor->session;
     1567  tr_info * inf = &tor->info;
     1568  const time_t now = tr_time ();
     1569
     1570  assert (!tor->isRunning);
     1571
     1572  tr_sessionLock (session);
     1573
     1574  tr_peerMgrRemoveTorrent (tor);
     1575
     1576  tr_announcerRemoveTorrent (session->announcer, tor);
     1577
     1578  tr_cpDestruct (&tor->completion);
     1579
     1580  tr_free (tor->downloadDir);
     1581  tr_free (tor->incompleteDir);
     1582
     1583  if (tor == session->torrentList)
     1584    {
     1585      session->torrentList = tor->next;
     1586    }
     1587  else for (t = session->torrentList; t != NULL; t = t->next)
     1588    {
     1589      if (t->next == tor)
     1590        {
     1591          t->next = tor->next;
     1592          break;
    15761593        }
    15771594    }
    15781595
    1579     /* decrement the torrent count */
    1580     assert (session->torrentCount >= 1);
    1581     session->torrentCount--;
    1582 
    1583     /* resequence the queue positions */
    1584     t = NULL;
    1585     while ((t = tr_torrentNext (session, t))) {
    1586         if (t->queuePosition > tor->queuePosition) {
    1587             t->queuePosition--;
    1588             t->anyDate = now;
     1596  /* decrement the torrent count */
     1597  assert (session->torrentCount >= 1);
     1598  session->torrentCount--;
     1599
     1600  /* resequence the queue positions */
     1601  t = NULL;
     1602  while ((t = tr_torrentNext (session, t)))
     1603    {
     1604      if (t->queuePosition > tor->queuePosition)
     1605        {
     1606          t->queuePosition--;
     1607          t->anyDate = now;
    15891608        }
    15901609    }
    1591     assert (queueIsSequenced (session));
    1592 
    1593     tr_bandwidthDestruct (&tor->bandwidth);
    1594 
    1595     tr_metainfoFree (inf);
    1596     memset (tor, ~0, sizeof (tr_torrent));
    1597     tr_free (tor);
    1598 
    1599     tr_sessionUnlock (session);
     1610  assert (queueIsSequenced (session));
     1611
     1612  tr_bandwidthDestruct (&tor->bandwidth);
     1613
     1614  tr_metainfoFree (inf);
     1615  memset (tor, ~0, sizeof (tr_torrent));
     1616  tr_free (tor);
     1617
     1618  tr_sessionUnlock (session);
    16001619}
    16011620
     
    16091628torrentStartImpl (void * vtor)
    16101629{
    1611     time_t now;
    1612     tr_torrent * tor = vtor;
    1613 
    1614     assert (tr_isTorrent (tor));
    1615 
    1616     tr_sessionLock (tor->session);
    1617 
    1618     tr_torrentRecheckCompleteness (tor);
    1619     torrentSetQueued (tor, false);
    1620 
    1621     now = tr_time ();
    1622     tor->isRunning = true;
    1623     tor->completeness = tr_cpGetStatus (&tor->completion);
    1624     tor->startDate = tor->anyDate = now;
    1625     tr_torrentClearError (tor);
    1626     tor->finishedSeedingByIdle = false;
    1627 
    1628     tr_torrentResetTransferStats (tor);
    1629     tr_announcerTorrentStarted (tor);
    1630     tor->dhtAnnounceAt = now + tr_cryptoWeakRandInt (20);
    1631     tor->dhtAnnounce6At = now + tr_cryptoWeakRandInt (20);
    1632     tor->lpdAnnounceAt = now;
    1633     tr_peerMgrStartTorrent (tor);
    1634 
    1635     tr_sessionUnlock (tor->session);
     1630  time_t now;
     1631  tr_torrent * tor = vtor;
     1632
     1633  assert (tr_isTorrent (tor));
     1634
     1635  tr_sessionLock (tor->session);
     1636
     1637  tr_torrentRecheckCompleteness (tor);
     1638  torrentSetQueued (tor, false);
     1639
     1640  now = tr_time ();
     1641  tor->isRunning = true;
     1642  tor->completeness = tr_cpGetStatus (&tor->completion);
     1643  tor->startDate = tor->anyDate = now;
     1644  tr_torrentClearError (tor);
     1645  tor->finishedSeedingByIdle = false;
     1646
     1647  tr_torrentResetTransferStats (tor);
     1648  tr_announcerTorrentStarted (tor);
     1649  tor->dhtAnnounceAt = now + tr_cryptoWeakRandInt (20);
     1650  tor->dhtAnnounce6At = now + tr_cryptoWeakRandInt (20);
     1651  tor->lpdAnnounceAt = now;
     1652  tr_peerMgrStartTorrent (tor);
     1653
     1654  tr_sessionUnlock (tor->session);
    16361655}
    16371656
     
    16391658tr_torrentGetCurrentSizeOnDisk (const tr_torrent * tor)
    16401659{
    1641     tr_file_index_t i;
    1642     uint64_t byte_count = 0;
    1643     const tr_file_index_t n = tor->info.fileCount;
    1644 
    1645     for (i=0; i<n; ++i)
    1646     {
    1647         struct stat sb;
    1648         char * filename = tr_torrentFindFile (tor, i);
    1649 
    1650         sb.st_size = 0;
    1651         if (filename && !stat (filename, &sb))
    1652             byte_count += sb.st_size;
    1653 
    1654         tr_free (filename);
    1655     }
    1656 
    1657     return byte_count;
     1660  tr_file_index_t i;
     1661  uint64_t byte_count = 0;
     1662  const tr_file_index_t n = tor->info.fileCount;
     1663
     1664  for (i=0; i<n; ++i)
     1665    {
     1666      struct stat sb;
     1667      char * filename = tr_torrentFindFile (tor, i);
     1668
     1669      sb.st_size = 0;
     1670      if (filename && !stat (filename, &sb))
     1671        byte_count += sb.st_size;
     1672
     1673      tr_free (filename);
     1674    }
     1675
     1676  return byte_count;
    16581677}
    16591678
     
    16611680torrentShouldQueue (const tr_torrent * tor)
    16621681{
    1663     const tr_direction dir = tr_torrentGetQueueDirection (tor);
    1664 
    1665     return tr_sessionCountQueueFreeSlots (tor->session, dir) == 0;
     1682  const tr_direction dir = tr_torrentGetQueueDirection (tor);
     1683
     1684  return tr_sessionCountQueueFreeSlots (tor->session, dir) == 0;
    16661685}
    16671686
     
    16691688torrentStart (tr_torrent * tor, bool bypass_queue)
    16701689{
    1671     switch (tr_torrentGetActivity (tor))
    1672     {
    1673         case TR_STATUS_SEED:
    1674         case TR_STATUS_DOWNLOAD:
    1675             return; /* already started */
    1676             break;
    1677 
    1678         case TR_STATUS_SEED_WAIT:
    1679         case TR_STATUS_DOWNLOAD_WAIT:
    1680             if (!bypass_queue)
    1681                 return; /* already queued */
    1682             break;
    1683 
    1684         case TR_STATUS_CHECK:
    1685         case TR_STATUS_CHECK_WAIT:
    1686             /* verifying right now... wait until that's done so
    1687              * we'll know what completeness to use/announce */
    1688             tor->startAfterVerify = true;
     1690  switch (tr_torrentGetActivity (tor))
     1691    {
     1692      case TR_STATUS_SEED:
     1693      case TR_STATUS_DOWNLOAD:
     1694        return; /* already started */
     1695        break;
     1696
     1697      case TR_STATUS_SEED_WAIT:
     1698      case TR_STATUS_DOWNLOAD_WAIT:
     1699        if (!bypass_queue)
     1700          return; /* already queued */
     1701        break;
     1702
     1703      case TR_STATUS_CHECK:
     1704      case TR_STATUS_CHECK_WAIT:
     1705        /* verifying right now... wait until that's done so
     1706         * we'll know what completeness to use/announce */
     1707        tor->startAfterVerify = true;
     1708        return;
     1709        break;
     1710
     1711      case TR_STATUS_STOPPED:
     1712        if (!bypass_queue && torrentShouldQueue (tor))
     1713          {
     1714            torrentSetQueued (tor, true);
    16891715            return;
    1690             break;
    1691 
    1692         case TR_STATUS_STOPPED:
    1693             if (!bypass_queue && torrentShouldQueue (tor)) {
    1694                 torrentSetQueued (tor, true);
    1695                 return;
    1696             }
    1697             break;
    1698     }
    1699 
    1700     /* don't allow the torrent to be started if the files disappeared */
    1701     if (setLocalErrorIfFilesDisappeared (tor))
    1702         return;
    1703 
    1704     /* otherwise, start it now... */
    1705     tr_sessionLock (tor->session);
    1706 
    1707     /* allow finished torrents to be resumed */
    1708     if (tr_torrentIsSeedRatioDone (tor)) {
    1709         tr_logAddTorInfo (tor, "%s", _("Restarted manually -- disabling its seed ratio"));
    1710         tr_torrentSetRatioMode (tor, TR_RATIOLIMIT_UNLIMITED);
    1711     }
    1712 
    1713     /* corresponds to the peer_id sent as a tracker request parameter.
    1714      * one tracker admin says: "When the same torrent is opened and
    1715      * closed and opened again without quitting Transmission ...
    1716      * change the peerid. It would help sometimes if a stopped event
    1717      * was missed to ensure that we didn't think someone was cheating. */
    1718     tr_torrentUnsetPeerId (tor);
    1719     tor->isRunning = true;
    1720     tr_torrentSetDirty (tor);
    1721     tr_runInEventThread (tor->session, torrentStartImpl, tor);
    1722 
    1723     tr_sessionUnlock (tor->session);
     1716          }
     1717        break;
     1718    }
     1719
     1720  /* don't allow the torrent to be started if the files disappeared */
     1721  if (setLocalErrorIfFilesDisappeared (tor))
     1722    return;
     1723
     1724  /* otherwise, start it now... */
     1725  tr_sessionLock (tor->session);
     1726
     1727  /* allow finished torrents to be resumed */
     1728  if (tr_torrentIsSeedRatioDone (tor))
     1729    {
     1730      tr_logAddTorInfo (tor, "%s", _("Restarted manually -- disabling its seed ratio"));
     1731      tr_torrentSetRatioMode (tor, TR_RATIOLIMIT_UNLIMITED);
     1732    }
     1733
     1734  /* corresponds to the peer_id sent as a tracker request parameter.
     1735   * one tracker admin says: "When the same torrent is opened and
     1736   * closed and opened again without quitting Transmission ...
     1737   * change the peerid. It would help sometimes if a stopped event
     1738   * was missed to ensure that we didn't think someone was cheating. */
     1739  tr_torrentUnsetPeerId (tor);
     1740  tor->isRunning = true;
     1741  tr_torrentSetDirty (tor);
     1742  tr_runInEventThread (tor->session, torrentStartImpl, tor);
     1743
     1744  tr_sessionUnlock (tor->session);
    17241745}
    17251746
     
    17271748tr_torrentStart (tr_torrent * tor)
    17281749{
    1729     if (tr_isTorrent (tor))
    1730         torrentStart (tor, false);
     1750  if (tr_isTorrent (tor))
     1751    torrentStart (tor, false);
    17311752}
    17321753
     
    17341755tr_torrentStartNow (tr_torrent * tor)
    17351756{
    1736     if (tr_isTorrent (tor))
    1737         torrentStart (tor, true);
     1757  if (tr_isTorrent (tor))
     1758    torrentStart (tor, true);
    17381759}
    17391760
     
    18181839tr_torrentSave (tr_torrent * tor)
    18191840{
    1820     assert (tr_isTorrent (tor));
    1821 
    1822     if (tor->isDirty)
    1823     {
    1824         tor->isDirty = false;
    1825         tr_torrentSaveResume (tor);
     1841  assert (tr_isTorrent (tor));
     1842
     1843  if (tor->isDirty)
     1844    {
     1845      tor->isDirty = false;
     1846      tr_torrentSaveResume (tor);
    18261847    }
    18271848}
     
    18541875tr_torrentStop (tr_torrent * tor)
    18551876{
    1856     assert (tr_isTorrent (tor));
    1857 
    1858     if (tr_isTorrent (tor))
    1859     {
    1860         tr_sessionLock (tor->session);
    1861 
    1862         tor->isRunning = 0;
    1863         tor->isStopping = 0;
    1864         tr_torrentSetDirty (tor);
    1865         tr_runInEventThread (tor->session, stopTorrent, tor);
    1866 
    1867         tr_sessionUnlock (tor->session);
     1877  assert (tr_isTorrent (tor));
     1878
     1879  if (tr_isTorrent (tor))
     1880    {
     1881      tr_sessionLock (tor->session);
     1882
     1883      tor->isRunning = 0;
     1884      tor->isStopping = 0;
     1885      tr_torrentSetDirty (tor);
     1886      tr_runInEventThread (tor->session, stopTorrent, tor);
     1887
     1888      tr_sessionUnlock (tor->session);
    18681889    }
    18691890}
     
    18721893closeTorrent (void * vtor)
    18731894{
    1874     tr_variant * d;
    1875     tr_torrent * tor = vtor;
    1876 
    1877     assert (tr_isTorrent (tor));
    1878 
    1879     d = tr_variantListAddDict (&tor->session->removedTorrents, 2);
    1880     tr_variantDictAddInt (d, TR_KEY_id, tor->uniqueId);
    1881     tr_variantDictAddInt (d, TR_KEY_date, tr_time ());
    1882 
    1883     tr_logAddTorInfo (tor, "%s", _("Removing torrent"));
    1884 
    1885     stopTorrent (tor);
    1886 
    1887     if (tor->isDeleting)
    1888     {
    1889         tr_metainfoRemoveSaved (tor->session, &tor->info);
    1890         tr_torrentRemoveResume (tor);
    1891     }
    1892 
    1893     tor->isRunning = 0;
    1894     freeTorrent (tor);
     1895  tr_variant * d;
     1896  tr_torrent * tor = vtor;
     1897
     1898  assert (tr_isTorrent (tor));
     1899
     1900  d = tr_variantListAddDict (&tor->session->removedTorrents, 2);
     1901  tr_variantDictAddInt (d, TR_KEY_id, tor->uniqueId);
     1902  tr_variantDictAddInt (d, TR_KEY_date, tr_time ());
     1903
     1904  tr_logAddTorInfo (tor, "%s", _("Removing torrent"));
     1905
     1906  stopTorrent (tor);
     1907
     1908  if (tor->isDeleting)
     1909    {
     1910      tr_metainfoRemoveSaved (tor->session, &tor->info);
     1911      tr_torrentRemoveResume (tor);
     1912    }
     1913
     1914  tor->isRunning = 0;
     1915  freeTorrent (tor);
    18951916}
    18961917
     
    19421963                  tr_fileFunc    deleteFunc)
    19431964{
    1944     struct remove_data * data;
    1945 
    1946     assert (tr_isTorrent (tor));
    1947     tor->isDeleting = 1;
    1948 
    1949     data = tr_new0 (struct remove_data, 1);
    1950     data->tor = tor;
    1951     data->deleteFlag = deleteFlag;
    1952     data->deleteFunc = deleteFunc;
    1953     tr_runInEventThread (tor->session, removeTorrent, data);
     1965  struct remove_data * data;
     1966
     1967  assert (tr_isTorrent (tor));
     1968  tor->isDeleting = 1;
     1969
     1970  data = tr_new0 (struct remove_data, 1);
     1971  data->tor = tor;
     1972  data->deleteFlag = deleteFlag;
     1973  data->deleteFunc = deleteFunc;
     1974  tr_runInEventThread (tor->session, removeTorrent, data);
    19541975}
    19551976
     
    19611982getCompletionString (int type)
    19621983{
    1963     switch (type)
    1964     {
    1965         /* Translators: this is a minor point that's safe to skip over, but FYI:
    1966            "Complete" and "Done" are specific, different terms in Transmission:
    1967            "Complete" means we've downloaded every file in the torrent.
    1968            "Done" means we're done downloading the files we wanted, but NOT all
    1969            that exist */
    1970         case TR_PARTIAL_SEED:
    1971             return _("Done");
    1972 
    1973         case TR_SEED:
    1974             return _("Complete");
    1975 
    1976         default:
    1977             return _("Incomplete");
     1984  switch (type)
     1985    {
     1986      /* Translators: this is a minor point that's safe to skip over, but FYI:
     1987         "Complete" and "Done" are specific, different terms in Transmission:
     1988         "Complete" means we've downloaded every file in the torrent.
     1989         "Done" means we're done downloading the files we wanted, but NOT all
     1990         that exist */
     1991      case TR_PARTIAL_SEED:
     1992        return _("Done");
     1993
     1994      case TR_SEED:
     1995        return _("Complete");
     1996
     1997      default:
     1998        return _("Incomplete");
    19781999    }
    19792000}
     
    19842005                        bool               wasRunning)
    19852006{
    1986     assert ((status == TR_LEECH)
    1987          || (status == TR_SEED)
    1988          || (status == TR_PARTIAL_SEED));
    1989 
    1990     if (tor->completeness_func)
    1991         tor->completeness_func (tor, status, wasRunning,
    1992                                 tor->completeness_func_user_data);
     2007  assert ((status == TR_LEECH)
     2008       || (status == TR_SEED)
     2009       || (status == TR_PARTIAL_SEED));
     2010
     2011  if (tor->completeness_func)
     2012    tor->completeness_func (tor, status, wasRunning,
     2013                            tor->completeness_func_user_data);
    19932014}
    19942015
     
    19982019                                   void                          * user_data)
    19992020{
    2000     assert (tr_isTorrent (tor));
    2001 
    2002     tor->completeness_func = func;
    2003     tor->completeness_func_user_data = user_data;
     2021  assert (tr_isTorrent (tor));
     2022
     2023  tor->completeness_func = func;
     2024  tor->completeness_func_user_data = user_data;
    20042025}
    20052026
     
    20072028tr_torrentClearCompletenessCallback (tr_torrent * torrent)
    20082029{
    2009     tr_torrentSetCompletenessCallback (torrent, NULL, NULL);
     2030  tr_torrentSetCompletenessCallback (torrent, NULL, NULL);
    20102031}
    20112032
     
    20152036                                    void                           * user_data)
    20162037{
    2017     assert (tr_isTorrent (tor));
    2018 
    2019     tor->ratio_limit_hit_func = func;
    2020     tor->ratio_limit_hit_func_user_data = user_data;
     2038  assert (tr_isTorrent (tor));
     2039
     2040  tor->ratio_limit_hit_func = func;
     2041  tor->ratio_limit_hit_func_user_data = user_data;
    20212042}
    20222043
     
    20242045tr_torrentClearRatioLimitHitCallback (tr_torrent * torrent)
    20252046{
    2026     tr_torrentSetRatioLimitHitCallback (torrent, NULL, NULL);
     2047  tr_torrentSetRatioLimitHitCallback (torrent, NULL, NULL);
    20272048}
    20282049
     
    20322053                                   void                          * user_data)
    20332054{
    2034     assert (tr_isTorrent (tor));
    2035 
    2036     tor->idle_limit_hit_func = func;
    2037     tor->idle_limit_hit_func_user_data = user_data;
     2055  assert (tr_isTorrent (tor));
     2056
     2057  tor->idle_limit_hit_func = func;
     2058  tor->idle_limit_hit_func_user_data = user_data;
    20382059}
    20392060
     
    20412062tr_torrentClearIdleLimitHitCallback (tr_torrent * torrent)
    20422063{
    2043     tr_torrentSetIdleLimitHitCallback (torrent, NULL, NULL);
     2064  tr_torrentSetIdleLimitHitCallback (torrent, NULL, NULL);
    20442065}
    20452066
     
    20472068onSigCHLD (int i UNUSED)
    20482069{
    2049     waitpid (-1, NULL, WNOHANG);
     2070  waitpid (-1, NULL, WNOHANG);
    20502071}
    20512072
     
    20532074torrentCallScript (const tr_torrent * tor, const char * script)
    20542075{
    2055     char timeStr[128];
    2056     const time_t now = tr_time ();
    2057 
    2058     tr_strlcpy (timeStr, ctime (&now), sizeof (timeStr));
    2059     *strchr (timeStr,'\n') = '\0';
    2060 
    2061     if (script && *script)
    2062     {
    2063         int i;
    2064         char * cmd[] = { tr_strdup (script), NULL };
    2065         char * env[] = {
    2066             tr_strdup_printf ("TR_APP_VERSION=%s", SHORT_VERSION_STRING),
    2067             tr_strdup_printf ("TR_TIME_LOCALTIME=%s", timeStr),
    2068             tr_strdup_printf ("TR_TORRENT_DIR=%s", tor->currentDir),
    2069             tr_strdup_printf ("TR_TORRENT_ID=%d", tr_torrentId (tor)),
    2070             tr_strdup_printf ("TR_TORRENT_HASH=%s", tor->info.hashString),
    2071             tr_strdup_printf ("TR_TORRENT_NAME=%s", tr_torrentName (tor)),
    2072             NULL };
    2073 
    2074         tr_logAddTorInfo (tor, "Calling script \"%s\"", script);
     2076  char timeStr[128];
     2077  const time_t now = tr_time ();
     2078
     2079  tr_strlcpy (timeStr, ctime (&now), sizeof (timeStr));
     2080  *strchr (timeStr,'\n') = '\0';
     2081
     2082  if (script && *script)
     2083    {
     2084      int i;
     2085      char * cmd[] = { tr_strdup (script), NULL };
     2086      char * env[] = {
     2087        tr_strdup_printf ("TR_APP_VERSION=%s", SHORT_VERSION_STRING),
     2088        tr_strdup_printf ("TR_TIME_LOCALTIME=%s", timeStr),
     2089        tr_strdup_printf ("TR_TORRENT_DIR=%s", tor->currentDir),
     2090        tr_strdup_printf ("TR_TORRENT_ID=%d", tr_torrentId (tor)),
     2091        tr_strdup_printf ("TR_TORRENT_HASH=%s", tor->info.hashString),
     2092        tr_strdup_printf ("TR_TORRENT_NAME=%s", tr_torrentName (tor)),
     2093        NULL };
     2094
     2095      tr_logAddTorInfo (tor, "Calling script \"%s\"", script);
    20752096
    20762097#ifdef WIN32
    2077         if (_spawnvpe (_P_NOWAIT, script, (const char*)cmd, env) == -1)
    2078           tr_logAddTorErr (tor, "error executing script \"%s\": %s", cmd[0], tr_strerror (errno));
     2098      if (_spawnvpe (_P_NOWAIT, script, (const char*)cmd, env) == -1)
     2099        tr_logAddTorErr (tor, "error executing script \"%s\": %s", cmd[0], tr_strerror (errno));
    20792100#else
    2080         signal (SIGCHLD, onSigCHLD);
    2081 
    2082         if (!fork ())
     2101      signal (SIGCHLD, onSigCHLD);
     2102
     2103      if (!fork ())
    20832104        {
    2084             for (i=0; env[i]; ++i)
    2085                 putenv (env[i]);
    2086 
    2087             if (execvp (script, cmd) == -1)
    2088               tr_logAddTorErr (tor, "error executing script \"%s\": %s", cmd[0], tr_strerror (errno));
    2089 
    2090             _exit (0);
     2105          for (i=0; env[i]; ++i)
     2106            putenv (env[i]);
     2107
     2108          if (execvp (script, cmd) == -1)
     2109            tr_logAddTorErr (tor, "error executing script \"%s\": %s", cmd[0], tr_strerror (errno));
     2110
     2111          _exit (0);
    20912112        }
    20922113#endif
    20932114
    2094         for (i=0; cmd[i]; ++i) tr_free (cmd[i]);
    2095         for (i=0; env[i]; ++i) tr_free (env[i]);
     2115      for (i=0; cmd[i]; ++i) tr_free (cmd[i]);
     2116      for (i=0; env[i]; ++i) tr_free (env[i]);
    20962117    }
    20972118}
     
    21592180tr_torrentFireMetadataCompleted (tr_torrent * tor)
    21602181{
    2161     assert (tr_isTorrent (tor));
    2162 
    2163     if (tor->metadata_func)
    2164         tor->metadata_func (tor, tor->metadata_func_user_data);
     2182  assert (tr_isTorrent (tor));
     2183
     2184  if (tor->metadata_func != NULL)
     2185    tor->metadata_func (tor, tor->metadata_func_user_data);
    21652186}
    21662187
     
    21702191                               void                      * user_data)
    21712192{
    2172     assert (tr_isTorrent (tor));
    2173 
    2174     tor->metadata_func = func;
    2175     tor->metadata_func_user_data = user_data;
     2193  assert (tr_isTorrent (tor));
     2194
     2195  tor->metadata_func = func;
     2196  tor->metadata_func_user_data = user_data;
    21762197}
    21772198
     
    21862207                            tr_priority_t   priority)
    21872208{
    2188     tr_piece_index_t i;
    2189     tr_file *        file;
    2190 
    2191     assert (tr_isTorrent (tor));
    2192     assert (fileIndex < tor->info.fileCount);
    2193     assert (tr_isPriority (priority));
    2194 
    2195     file = &tor->info.files[fileIndex];
    2196     file->priority = priority;
    2197     for (i = file->firstPiece; i <= file->lastPiece; ++i)
    2198         tor->info.pieces[i].priority = calculatePiecePriority (tor, i, fileIndex);
     2209  tr_file * file;
     2210  tr_piece_index_t i;
     2211
     2212  assert (tr_isTorrent (tor));
     2213  assert (fileIndex < tor->info.fileCount);
     2214  assert (tr_isPriority (priority));
     2215
     2216  file = &tor->info.files[fileIndex];
     2217  file->priority = priority;
     2218  for (i=file->firstPiece; i<=file->lastPiece; ++i)
     2219    tor->info.pieces[i].priority = calculatePiecePriority (tor, i, fileIndex);
    21992220}
    22002221
     
    22052226                             tr_priority_t            priority)
    22062227{
    2207     tr_file_index_t i;
    2208     assert (tr_isTorrent (tor));
    2209     tr_torrentLock (tor);
    2210 
    2211     for (i = 0; i < fileCount; ++i)
    2212         if (files[i] < tor->info.fileCount)
    2213             tr_torrentInitFilePriority (tor, files[i], priority);
    2214     tr_torrentSetDirty (tor);
    2215     tr_peerMgrRebuildRequests (tor);
    2216 
    2217     tr_torrentUnlock (tor);
     2228  tr_file_index_t i;
     2229  assert (tr_isTorrent (tor));
     2230  tr_torrentLock (tor);
     2231
     2232  for (i=0; i<fileCount; ++i)
     2233    if (files[i] < tor->info.fileCount)
     2234      tr_torrentInitFilePriority (tor, files[i], priority);
     2235  tr_torrentSetDirty (tor);
     2236  tr_peerMgrRebuildRequests (tor);
     2237
     2238  tr_torrentUnlock (tor);
    22182239}
    22192240
     
    22412262setFileDND (tr_torrent * tor, tr_file_index_t fileIndex, int doDownload)
    22422263{
    2243     const int8_t    dnd = !doDownload;
    2244     tr_piece_index_t firstPiece;
    2245     int8_t          firstPieceDND;
    2246     tr_piece_index_t lastPiece;
    2247     int8_t          lastPieceDND;
    2248     tr_file_index_t  i;
    2249     tr_file *        file = &tor->info.files[fileIndex];
    2250 
    2251     file->dnd = dnd;
    2252     firstPiece = file->firstPiece;
    2253     lastPiece = file->lastPiece;
    2254 
    2255     /* can't set the first piece to DND unless
    2256        every file using that piece is DND */
    2257     firstPieceDND = dnd;
    2258     if (fileIndex > 0)
    2259     {
    2260         for (i = fileIndex - 1; firstPieceDND; --i)
     2264  const int8_t dnd = !doDownload;
     2265  tr_piece_index_t firstPiece;
     2266  int8_t firstPieceDND;
     2267  tr_piece_index_t lastPiece;
     2268  int8_t lastPieceDND;
     2269  tr_file_index_t  i;
     2270  tr_file * file = &tor->info.files[fileIndex];
     2271
     2272  file->dnd = dnd;
     2273  firstPiece = file->firstPiece;
     2274  lastPiece = file->lastPiece;
     2275
     2276  /* can't set the first piece to DND unless
     2277     every file using that piece is DND */
     2278  firstPieceDND = dnd;
     2279  if (fileIndex > 0)
     2280    {
     2281      for (i=fileIndex-1; firstPieceDND; --i)
    22612282        {
    2262             if (tor->info.files[i].lastPiece != firstPiece)
    2263                 break;
    2264             firstPieceDND = tor->info.files[i].dnd;
    2265             if (!i)
    2266                 break;
     2283          if (tor->info.files[i].lastPiece != firstPiece)
     2284            break;
     2285
     2286          firstPieceDND = tor->info.files[i].dnd;
     2287          if (!i)
     2288            break;
    22672289        }
    22682290    }
    22692291
    2270     /* can't set the last piece to DND unless
    2271        every file using that piece is DND */
    2272     lastPieceDND = dnd;
    2273     for (i = fileIndex + 1; lastPieceDND && i < tor->info.fileCount; ++i)
    2274     {
    2275         if (tor->info.files[i].firstPiece != lastPiece)
    2276             break;
    2277         lastPieceDND = tor->info.files[i].dnd;
    2278     }
    2279 
    2280     if (firstPiece == lastPiece)
    2281     {
    2282         tor->info.pieces[firstPiece].dnd = firstPieceDND && lastPieceDND;
    2283     }
    2284     else
    2285     {
    2286         tr_piece_index_t pp;
    2287         tor->info.pieces[firstPiece].dnd = firstPieceDND;
    2288         tor->info.pieces[lastPiece].dnd = lastPieceDND;
    2289         for (pp = firstPiece + 1; pp < lastPiece; ++pp)
    2290             tor->info.pieces[pp].dnd = dnd;
     2292  /* can't set the last piece to DND unless
     2293     every file using that piece is DND */
     2294  lastPieceDND = dnd;
     2295  for (i=fileIndex+1; lastPieceDND && i<tor->info.fileCount; ++i)
     2296    {
     2297      if (tor->info.files[i].firstPiece != lastPiece)
     2298        break;
     2299      lastPieceDND = tor->info.files[i].dnd;
     2300    }
     2301
     2302  if (firstPiece == lastPiece)
     2303    {
     2304      tor->info.pieces[firstPiece].dnd = firstPieceDND && lastPieceDND;
     2305    }
     2306  else
     2307    {
     2308      tr_piece_index_t pp;
     2309      tor->info.pieces[firstPiece].dnd = firstPieceDND;
     2310      tor->info.pieces[lastPiece].dnd = lastPieceDND;
     2311      for (pp=firstPiece+1; pp<lastPiece; ++pp)
     2312        tor->info.pieces[pp].dnd = dnd;
    22912313    }
    22922314}
     
    22982320                       bool                     doDownload)
    22992321{
    2300     tr_file_index_t i;
    2301 
    2302     assert (tr_isTorrent (tor));
    2303 
    2304     tr_torrentLock (tor);
    2305 
    2306     for (i=0; i<fileCount; ++i)
    2307         if (files[i] < tor->info.fileCount)
    2308             setFileDND (tor, files[i], doDownload);
    2309 
    2310     tr_cpInvalidateDND (&tor->completion);
    2311 
    2312     tr_torrentUnlock (tor);
     2322  tr_file_index_t i;
     2323
     2324  assert (tr_isTorrent (tor));
     2325
     2326  tr_torrentLock (tor);
     2327
     2328  for (i=0; i<fileCount; ++i)
     2329    if (files[i] < tor->info.fileCount)
     2330      setFileDND (tor, files[i], doDownload);
     2331
     2332  tr_cpInvalidateDND (&tor->completion);
     2333
     2334  tr_torrentUnlock (tor);
    23132335}
    23142336
     
    23192341                      bool                     doDownload)
    23202342{
    2321     assert (tr_isTorrent (tor));
    2322     tr_torrentLock (tor);
    2323 
    2324     tr_torrentInitFileDLs (tor, files, fileCount, doDownload);
    2325     tr_torrentSetDirty (tor);
    2326     tr_torrentRecheckCompleteness (tor);
    2327     tr_peerMgrRebuildRequests (tor);
    2328 
    2329     tr_torrentUnlock (tor);
     2343  assert (tr_isTorrent (tor));
     2344  tr_torrentLock (tor);
     2345
     2346  tr_torrentInitFileDLs (tor, files, fileCount, doDownload);
     2347  tr_torrentSetDirty (tor);
     2348  tr_torrentRecheckCompleteness (tor);
     2349  tr_peerMgrRebuildRequests (tor);
     2350
     2351  tr_torrentUnlock (tor);
    23302352}
    23312353
     
    23372359tr_torrentGetPriority (const tr_torrent * tor)
    23382360{
    2339     assert (tr_isTorrent (tor));
    2340 
    2341     return tor->bandwidth.priority;
     2361  assert (tr_isTorrent (tor));
     2362
     2363  return tor->bandwidth.priority;
    23422364}
    23432365
     
    23452367tr_torrentSetPriority (tr_torrent * tor, tr_priority_t priority)
    23462368{
    2347     assert (tr_isTorrent (tor));
    2348     assert (tr_isPriority (priority));
    2349 
    2350     if (tor->bandwidth.priority != priority)
    2351     {
    2352         tor->bandwidth.priority = priority;
    2353 
    2354         tr_torrentSetDirty (tor);
     2369  assert (tr_isTorrent (tor));
     2370  assert (tr_isPriority (priority));
     2371
     2372  if (tor->bandwidth.priority != priority)
     2373    {
     2374      tor->bandwidth.priority = priority;
     2375
     2376      tr_torrentSetDirty (tor);
    23552377    }
    23562378}
     
    23642386                        uint16_t     maxConnectedPeers)
    23652387{
    2366     assert (tr_isTorrent (tor));
    2367 
    2368     if (tor->maxConnectedPeers != maxConnectedPeers)
    2369     {
    2370         tor->maxConnectedPeers = maxConnectedPeers;
    2371 
    2372         tr_torrentSetDirty (tor);
     2388  assert (tr_isTorrent (tor));
     2389
     2390  if (tor->maxConnectedPeers != maxConnectedPeers)
     2391    {
     2392      tor->maxConnectedPeers = maxConnectedPeers;
     2393
     2394      tr_torrentSetDirty (tor);
    23732395    }
    23742396}
     
    23772399tr_torrentGetPeerLimit (const tr_torrent * tor)
    23782400{
    2379     assert (tr_isTorrent (tor));
    2380 
    2381     return tor->maxConnectedPeers;
     2401  assert (tr_isTorrent (tor));
     2402
     2403  return tor->maxConnectedPeers;
    23822404}
    23832405
     
    23932415                            uint32_t         * length)
    23942416{
    2395     uint64_t pos = block;
    2396     pos *= tor->blockSize;
    2397     *piece = pos / tor->info.pieceSize;
    2398     *offset = pos - (*piece * tor->info.pieceSize);
    2399     *length = tr_torBlockCountBytes (tor, block);
     2417  uint64_t pos = block;
     2418  pos *= tor->blockSize;
     2419  *piece = pos / tor->info.pieceSize;
     2420  *offset = pos - (*piece * tor->info.pieceSize);
     2421  *length = tr_torBlockCountBytes (tor, block);
    24002422}
    24012423
     
    24062428           uint32_t           offset)
    24072429{
    2408     tr_block_index_t ret;
    2409 
    2410     assert (tr_isTorrent (tor));
    2411 
    2412     ret = index;
    2413     ret *= (tor->info.pieceSize / tor->blockSize);
    2414     ret += offset / tor->blockSize;
    2415     return ret;
     2430  tr_block_index_t ret;
     2431
     2432  assert (tr_isTorrent (tor));
     2433
     2434  ret = index;
     2435  ret *= (tor->info.pieceSize / tor->blockSize);
     2436  ret += offset / tor->blockSize;
     2437  return ret;
    24162438}
    24172439
     
    24222444                      uint32_t           length)
    24232445{
    2424     int err = 0;
    2425 
    2426     assert (tr_isTorrent (tor));
    2427 
    2428     if (index >= tor->info.pieceCount)
    2429         err = 1;
    2430     else if (length < 1)
    2431         err = 2;
    2432     else if ((offset + length) > tr_torPieceCountBytes (tor, index))
    2433         err = 3;
    2434     else if (length > MAX_BLOCK_SIZE)
    2435         err = 4;
    2436     else if (tr_pieceOffset (tor, index, offset, length) > tor->info.totalSize)
    2437         err = 5;
    2438 
    2439     if (err) tr_logAddTorDbg (tor, "index %lu offset %lu length %lu err %d\n",
    2440                             (unsigned long)index,
    2441                             (unsigned long)offset,
    2442                             (unsigned long)length,
    2443                               err);
    2444 
    2445     return !err;
     2446  int err = 0;
     2447
     2448  assert (tr_isTorrent (tor));
     2449
     2450  if (index >= tor->info.pieceCount)
     2451    err = 1;
     2452  else if (length < 1)
     2453    err = 2;
     2454  else if ((offset + length) > tr_torPieceCountBytes (tor, index))
     2455    err = 3;
     2456  else if (length > MAX_BLOCK_SIZE)
     2457    err = 4;
     2458  else if (tr_pieceOffset (tor, index, offset, length) > tor->info.totalSize)
     2459    err = 5;
     2460
     2461  if (err)
     2462    tr_logAddTorDbg (tor, "index %lu offset %lu length %lu err %d\n",
     2463                     (unsigned long)index,
     2464                     (unsigned long)offset,
     2465                     (unsigned long)length,
     2466                     err);
     2467
     2468  return !err;
    24462469}
    24472470
     
    24522475                uint32_t           length)
    24532476{
    2454     uint64_t ret;
    2455 
    2456     assert (tr_isTorrent (tor));
    2457 
    2458     ret = tor->info.pieceSize;
    2459     ret *= index;
    2460     ret += offset;
    2461     ret += length;
    2462     return ret;
     2477  uint64_t ret;
     2478
     2479  assert (tr_isTorrent (tor));
     2480
     2481  ret = tor->info.pieceSize;
     2482  ret *= index;
     2483  ret += offset;
     2484  ret += length;
     2485  return ret;
    24632486}
    24642487
     
    24692492                         tr_block_index_t        * last)
    24702493{
    2471     const tr_file * f = &tor->info.files[file];
    2472     uint64_t offset = f->offset;
    2473     *first = offset / tor->blockSize;
    2474     if (!f->length)
    2475         *last = *first;
    2476     else {
    2477         offset += f->length - 1;
    2478         *last = offset / tor->blockSize;
     2494  const tr_file * f = &tor->info.files[file];
     2495  uint64_t offset = f->offset;
     2496
     2497  *first = offset / tor->blockSize;
     2498
     2499  if (!f->length)
     2500    {
     2501      *last = *first;
     2502    }
     2503  else
     2504    {
     2505      offset += f->length - 1;
     2506      *last = offset / tor->blockSize;
    24792507    }
    24802508}
     
    24862514                          tr_block_index_t        * last)
    24872515{
    2488     uint64_t offset = tor->info.pieceSize;
    2489     offset *= piece;
    2490     *first = offset / tor->blockSize;
    2491     offset += (tr_torPieceCountBytes (tor, piece) - 1);
    2492     *last = offset / tor->blockSize;
     2516  uint64_t offset = tor->info.pieceSize;
     2517  offset *= piece;
     2518  *first = offset / tor->blockSize;
     2519  offset += (tr_torPieceCountBytes (tor, piece) - 1);
     2520  *last = offset / tor->blockSize;
    24932521}
    24942522
     
    25012529tr_torrentSetPieceChecked (tr_torrent * tor, tr_piece_index_t pieceIndex)
    25022530{
    2503     assert (tr_isTorrent (tor));
    2504     assert (pieceIndex < tor->info.pieceCount);
    2505 
    2506     tor->info.pieces[pieceIndex].timeChecked = tr_time ();
     2531  assert (tr_isTorrent (tor));
     2532  assert (pieceIndex < tor->info.pieceCount);
     2533
     2534  tor->info.pieces[pieceIndex].timeChecked = tr_time ();
    25072535}
    25082536
     
    25102538tr_torrentSetChecked (tr_torrent * tor, time_t when)
    25112539{
    2512     tr_piece_index_t i, n;
    2513 
    2514     assert (tr_isTorrent (tor));
    2515 
    2516     for (i=0, n=tor->info.pieceCount; i!=n; ++i)
    2517         tor->info.pieces[i].timeChecked = when;
     2540  tr_piece_index_t i, n;
     2541
     2542  assert (tr_isTorrent (tor));
     2543
     2544  for (i=0, n=tor->info.pieceCount; i!=n; ++i)
     2545    tor->info.pieces[i].timeChecked = when;
    25182546}
    25192547
     
    25212549tr_torrentCheckPiece (tr_torrent * tor, tr_piece_index_t pieceIndex)
    25222550{
    2523     const bool pass = tr_ioTestPiece (tor, pieceIndex);
    2524 
    2525     tr_deeplog_tor (tor, "[LAZY] tr_torrentCheckPiece tested piece %zu, pass==%d", (size_t)pieceIndex, (int)pass);
    2526     tr_torrentSetHasPiece (tor, pieceIndex, pass);
    2527     tr_torrentSetPieceChecked (tor, pieceIndex);
    2528     tor->anyDate = tr_time ();
    2529     tr_torrentSetDirty (tor);
    2530 
    2531     return pass;
     2551  const bool pass = tr_ioTestPiece (tor, pieceIndex);
     2552
     2553  tr_deeplog_tor (tor, "[LAZY] tr_torrentCheckPiece tested piece %zu, pass==%d", (size_t)pieceIndex, (int)pass);
     2554  tr_torrentSetHasPiece (tor, pieceIndex, pass);
     2555  tr_torrentSetPieceChecked (tor, pieceIndex);
     2556  tor->anyDate = tr_time ();
     2557  tr_torrentSetDirty (tor);
     2558
     2559  return pass;
    25322560}
    25332561
     
    25352563tr_torrentGetFileMTime (const tr_torrent * tor, tr_file_index_t i)
    25362564{
    2537     time_t mtime = 0;
    2538     if (!tr_fdFileGetCachedMTime (tor->session, tor->uniqueId, i, &mtime))
    2539         tr_torrentFindFile2 (tor, i, NULL, NULL, &mtime);
    2540     return mtime;
     2565  time_t mtime = 0;
     2566
     2567  if (!tr_fdFileGetCachedMTime (tor->session, tor->uniqueId, i, &mtime))
     2568    tr_torrentFindFile2 (tor, i, NULL, NULL, &mtime);
     2569
     2570  return mtime;
    25412571}
    25422572
     
    25442574tr_torrentPieceNeedsCheck (const tr_torrent * tor, tr_piece_index_t p)
    25452575{
    2546     uint64_t unused;
    2547     tr_file_index_t f;
    2548     const tr_info * inf = tr_torrentInfo (tor);
    2549 
    2550     /* if we've never checked this piece, then it needs to be checked */
    2551     if (!inf->pieces[p].timeChecked)
     2576  uint64_t unused;
     2577  tr_file_index_t f;
     2578  const tr_info * inf = tr_torrentInfo (tor);
     2579
     2580  /* if we've never checked this piece, then it needs to be checked */
     2581  if (!inf->pieces[p].timeChecked)
     2582    return true;
     2583
     2584  /* If we think we've completed one of the files in this piece,
     2585   * but it's been modified since we last checked it,
     2586   * then it needs to be rechecked */
     2587  tr_ioFindFileLocation (tor, p, 0, &f, &unused);
     2588  for (; f < inf->fileCount && pieceHasFile (p, &inf->files[f]); ++f)
     2589    if (tr_cpFileIsComplete (&tor->completion, f))
     2590      if (tr_torrentGetFileMTime (tor, f) > inf->pieces[p].timeChecked)
    25522591        return true;
    25532592
    2554     /* If we think we've completed one of the files in this piece,
    2555      * but it's been modified since we last checked it,
    2556      * then it needs to be rechecked */
    2557     tr_ioFindFileLocation (tor, p, 0, &f, &unused);
    2558     for (; f < inf->fileCount && pieceHasFile (p, &inf->files[f]); ++f)
    2559         if (tr_cpFileIsComplete (&tor->completion, f))
    2560             if (tr_torrentGetFileMTime (tor, f) > inf->pieces[p].timeChecked)
    2561                 return true;
    2562 
    2563     return false;
     2593  return false;
    25642594}
    25652595
     
    25712601compareTrackerByTier (const void * va, const void * vb)
    25722602{
    2573     const tr_tracker_info * a = va;
    2574     const tr_tracker_info * b = vb;
    2575 
    2576     /* sort by tier */
    2577     if (a->tier != b->tier)
    2578         return a->tier - b->tier;
    2579 
    2580     /* get the effects of a stable sort by comparing the two elements' addresses */
    2581     return a - b;
     2603  const tr_tracker_info * a = va;
     2604  const tr_tracker_info * b = vb;
     2605
     2606  /* sort by tier */
     2607  if (a->tier != b->tier)
     2608    return a->tier - b->tier;
     2609
     2610  /* get the effects of a stable sort by comparing the two elements' addresses */
     2611  return a - b;
    25822612}
    25832613
     
    25872617                           int                      trackerCount)
    25882618{
    2589     int i;
    2590     tr_variant metainfo;
    2591     bool ok = true;
    2592     tr_tracker_info * trackers;
    2593 
    2594     tr_torrentLock (tor);
    2595 
    2596     assert (tr_isTorrent (tor));
    2597 
    2598     /* ensure the trackers' tiers are in ascending order */
    2599     trackers = tr_memdup (trackers_in, sizeof (tr_tracker_info) * trackerCount);
    2600     qsort (trackers, trackerCount, sizeof (tr_tracker_info), compareTrackerByTier);
    2601 
    2602     /* look for bad URLs */
    2603     for (i=0; ok && i<trackerCount; ++i)
    2604         if (!tr_urlIsValidTracker (trackers[i].announce))
    2605             ok = false;
    2606 
    2607     /* save to the .torrent file */
    2608     if (ok && !tr_variantFromFile (&metainfo, TR_VARIANT_FMT_BENC, tor->info.torrent))
    2609     {
    2610         bool hasInfo;
    2611         tr_info tmpInfo;
    2612 
    2613         /* remove the old fields */
    2614         tr_variantDictRemove (&metainfo, TR_KEY_announce);
    2615         tr_variantDictRemove (&metainfo, TR_KEY_announce_list);
    2616 
    2617         /* add the new fields */
    2618         if (trackerCount > 0)
     2619  int i;
     2620  tr_variant metainfo;
     2621  bool ok = true;
     2622  tr_tracker_info * trackers;
     2623
     2624  tr_torrentLock (tor);
     2625
     2626  assert (tr_isTorrent (tor));
     2627
     2628  /* ensure the trackers' tiers are in ascending order */
     2629  trackers = tr_memdup (trackers_in, sizeof (tr_tracker_info) * trackerCount);
     2630  qsort (trackers, trackerCount, sizeof (tr_tracker_info), compareTrackerByTier);
     2631
     2632  /* look for bad URLs */
     2633  for (i=0; ok && i<trackerCount; ++i)
     2634    if (!tr_urlIsValidTracker (trackers[i].announce))
     2635      ok = false;
     2636
     2637  /* save to the .torrent file */
     2638  if (ok && !tr_variantFromFile (&metainfo, TR_VARIANT_FMT_BENC, tor->info.torrent))
     2639    {
     2640      bool hasInfo;
     2641      tr_info tmpInfo;
     2642
     2643      /* remove the old fields */
     2644      tr_variantDictRemove (&metainfo, TR_KEY_announce);
     2645      tr_variantDictRemove (&metainfo, TR_KEY_announce_list);
     2646
     2647      /* add the new fields */
     2648      if (trackerCount > 0)
    26192649        {
    2620             tr_variantDictAddStr (&metainfo, TR_KEY_announce, trackers[0].announce);
     2650          tr_variantDictAddStr (&metainfo, TR_KEY_announce, trackers[0].announce);
    26212651        }
    2622         if (trackerCount > 1)
     2652      if (trackerCount > 1)
    26232653        {
    2624             int i;
    2625             int prevTier = -1;
    2626             tr_variant * tier = NULL;
    2627             tr_variant * announceList = tr_variantDictAddList (&metainfo, TR_KEY_announce_list, 0);
    2628 
    2629             for (i=0; i<trackerCount; ++i) {
    2630                 if (prevTier != trackers[i].tier) {
    2631                     prevTier = trackers[i].tier;
    2632                     tier = tr_variantListAddList (announceList, 0);
     2654          int i;
     2655          int prevTier = -1;
     2656          tr_variant * tier = NULL;
     2657          tr_variant * announceList = tr_variantDictAddList (&metainfo, TR_KEY_announce_list, 0);
     2658
     2659          for (i=0; i<trackerCount; ++i)
     2660            {
     2661              if (prevTier != trackers[i].tier)
     2662                {
     2663                  prevTier = trackers[i].tier;
     2664                  tier = tr_variantListAddList (announceList, 0);
    26332665                }
    2634                 tr_variantListAddStr (tier, trackers[i].announce);
     2666
     2667              tr_variantListAddStr (tier, trackers[i].announce);
    26352668            }
    26362669        }
    26372670
    2638         /* try to parse it back again, to make sure it's good */
    2639         memset (&tmpInfo, 0, sizeof (tr_info));
    2640         if (tr_metainfoParse (tor->session, &metainfo, &tmpInfo,
    2641                               &hasInfo, &tor->infoDictLength))
     2671      /* try to parse it back again, to make sure it's good */
     2672      memset (&tmpInfo, 0, sizeof (tr_info));
     2673      if (tr_metainfoParse (tor->session, &metainfo, &tmpInfo,
     2674                            &hasInfo, &tor->infoDictLength))
    26422675        {
    2643             /* it's good, so keep these new trackers and free the old ones */
    2644 
    2645             tr_info swap;
    2646             swap.trackers = tor->info.trackers;
    2647             swap.trackerCount = tor->info.trackerCount;
    2648             tor->info.trackers = tmpInfo.trackers;
    2649             tor->info.trackerCount = tmpInfo.trackerCount;
    2650             tmpInfo.trackers = swap.trackers;
    2651             tmpInfo.trackerCount = swap.trackerCount;
    2652 
    2653             tr_metainfoFree (&tmpInfo);
    2654             tr_variantToFile (&metainfo, TR_VARIANT_FMT_BENC, tor->info.torrent);
     2676          /* it's good, so keep these new trackers and free the old ones */
     2677
     2678          tr_info swap;
     2679          swap.trackers = tor->info.trackers;
     2680          swap.trackerCount = tor->info.trackerCount;
     2681          tor->info.trackers = tmpInfo.trackers;
     2682          tor->info.trackerCount = tmpInfo.trackerCount;
     2683          tmpInfo.trackers = swap.trackers;
     2684          tmpInfo.trackerCount = swap.trackerCount;
     2685
     2686          tr_metainfoFree (&tmpInfo);
     2687          tr_variantToFile (&metainfo, TR_VARIANT_FMT_BENC, tor->info.torrent);
    26552688        }
    26562689
    2657         /* cleanup */
    2658         tr_variantFree (&metainfo);
    2659 
    2660         /* if we had a tracker-related error on this torrent,
    2661          * and that tracker's been removed,
    2662          * then clear the error */
    2663         if ((tor->error == TR_STAT_TRACKER_WARNING)
    2664             || (tor->error == TR_STAT_TRACKER_ERROR))
     2690      /* cleanup */
     2691      tr_variantFree (&metainfo);
     2692
     2693      /* if we had a tracker-related error on this torrent,
     2694       * and that tracker's been removed,
     2695       * then clear the error */
     2696      if ((tor->error == TR_STAT_TRACKER_WARNING)
     2697          || (tor->error == TR_STAT_TRACKER_ERROR))
    26652698        {
    2666             bool clear = true;
    2667 
    2668             for (i=0; clear && i<trackerCount; ++i)
    2669                 if (!strcmp (trackers[i].announce, tor->errorTracker))
    2670                     clear = false;
    2671 
    2672             if (clear)
    2673                 tr_torrentClearError (tor);
     2699          bool clear = true;
     2700
     2701          for (i=0; clear && i<trackerCount; ++i)
     2702            if (!strcmp (trackers[i].announce, tor->errorTracker))
     2703              clear = false;
     2704
     2705          if (clear)
     2706            tr_torrentClearError (tor);
    26742707        }
    26752708
    2676         /* tell the announcer to reload this torrent's tracker list */
    2677         tr_announcerResetTorrent (tor->session->announcer, tor);
    2678     }
    2679 
    2680     tr_torrentUnlock (tor);
    2681 
    2682     tr_free (trackers);
    2683     return ok;
     2709      /* tell the announcer to reload this torrent's tracker list */
     2710      tr_announcerResetTorrent (tor->session->announcer, tor);
     2711    }
     2712
     2713  tr_torrentUnlock (tor);
     2714
     2715  tr_free (trackers);
     2716  return ok;
    26842717}
    26852718
     
    26922725                        time_t       t)
    26932726{
    2694     assert (tr_isTorrent (tor));
    2695 
    2696     tor->addedDate = t;
    2697     tor->anyDate = MAX (tor->anyDate, tor->addedDate);
     2727  assert (tr_isTorrent (tor));
     2728
     2729  tor->addedDate = t;
     2730  tor->anyDate = MAX (tor->anyDate, tor->addedDate);
    26982731}
    26992732
     
    27012734tr_torrentSetActivityDate (tr_torrent * tor, time_t t)
    27022735{
    2703     assert (tr_isTorrent (tor));
    2704 
    2705     tor->activityDate = t;
    2706     tor->anyDate = MAX (tor->anyDate, tor->activityDate);
     2736  assert (tr_isTorrent (tor));
     2737
     2738  tor->activityDate = t;
     2739  tor->anyDate = MAX (tor->anyDate, tor->activityDate);
    27072740}
    27082741
     
    27112744                       time_t       t)
    27122745{
    2713     assert (tr_isTorrent (tor));
    2714 
    2715     tor->doneDate = t;
    2716     tor->anyDate = MAX (tor->anyDate, tor->doneDate);
     2746  assert (tr_isTorrent (tor));
     2747
     2748  tor->doneDate = t;
     2749  tor->anyDate = MAX (tor->anyDate, tor->doneDate);
    27172750}
    27182751
     
    27242757tr_torrentGetBytesLeftToAllocate (const tr_torrent * tor)
    27252758{
    2726     tr_file_index_t i;
    2727     uint64_t bytesLeft = 0;
    2728 
    2729     assert (tr_isTorrent (tor));
    2730 
    2731     for (i=0; i<tor->info.fileCount; ++i)
    2732     {
    2733         if (!tor->info.files[i].dnd)
     2759  tr_file_index_t i;
     2760  uint64_t bytesLeft = 0;
     2761
     2762  assert (tr_isTorrent (tor));
     2763
     2764  for (i=0; i<tor->info.fileCount; ++i)
     2765    {
     2766      if (!tor->info.files[i].dnd)
    27342767        {
    2735             struct stat sb;
    2736             const uint64_t length = tor->info.files[i].length;
    2737             char * path = tr_torrentFindFile (tor, i);
    2738 
    2739             bytesLeft += length;
    2740 
    2741             if ((path != NULL) && !stat (path, &sb)
    2742                                  && S_ISREG (sb.st_mode)
    2743                                  && ((uint64_t)sb.st_size <= length))
    2744                 bytesLeft -= sb.st_size;
    2745 
    2746             tr_free (path);
     2768          struct stat sb;
     2769          const uint64_t length = tor->info.files[i].length;
     2770          char * path = tr_torrentFindFile (tor, i);
     2771
     2772          bytesLeft += length;
     2773
     2774          if ((path != NULL) && !stat (path, &sb)
     2775                             && S_ISREG (sb.st_mode)
     2776                             && ((uint64_t)sb.st_size <= length))
     2777            bytesLeft -= sb.st_size;
     2778
     2779          tr_free (path);
    27472780        }
    27482781    }
    27492782
    2750     return bytesLeft;
     2783  return bytesLeft;
    27512784}
    27522785
     
    27582791isJunkFile (const char * base)
    27592792{
    2760     int i;
    2761     static const char * files[] = { ".DS_Store", "desktop.ini", "Thumbs.db" };
    2762     static const int file_count = sizeof (files) / sizeof (files[0]);
    2763 
    2764     for (i=0; i<file_count; ++i)
    2765         if (!strcmp (base, files[i]))
    2766             return true;
     2793  int i;
     2794  static const char * files[] = { ".DS_Store", "desktop.ini", "Thumbs.db" };
     2795  static const int file_count = sizeof (files) / sizeof (files[0]);
     2796
     2797  for (i=0; i<file_count; ++i)
     2798    if (!strcmp (base, files[i]))
     2799      return true;
    27672800
    27682801#ifdef SYS_DARWIN
    2769     /* check for resource forks. <http://support.apple.com/kb/TA20578> */
    2770     if (!memcmp (base, "._", 2))
    2771         return true;
     2802  /* check for resource forks. <http://support.apple.com/kb/TA20578> */
     2803  if (!memcmp (base, "._", 2))
     2804    return true;
    27722805#endif
    27732806
    2774     return false;
     2807  return false;
    27752808}
    27762809
     
    27782811removeEmptyFoldersAndJunkFiles (const char * folder)
    27792812{
    2780     DIR * odir;
    2781     if ((odir = opendir (folder))) {
    2782         struct dirent * d;
    2783         while ((d = readdir (odir))) {
    2784             if (strcmp (d->d_name, ".") && strcmp (d->d_name, "..")) {
    2785                 struct stat sb;
    2786                 char * filename = tr_buildPath (folder, d->d_name, NULL);
    2787                 if (!stat (filename, &sb) && S_ISDIR (sb.st_mode))
    2788                     removeEmptyFoldersAndJunkFiles (filename);
    2789                 else if (isJunkFile (d->d_name))
    2790                     tr_remove (filename);
    2791                 tr_free (filename);
     2813  DIR * odir;
     2814
     2815  if ((odir = opendir (folder)))
     2816    {
     2817      struct dirent * d;
     2818      while ((d = readdir (odir)))
     2819        {
     2820          if (strcmp (d->d_name, ".") && strcmp (d->d_name, ".."))
     2821            {
     2822              struct stat sb;
     2823              char * filename = tr_buildPath (folder, d->d_name, NULL);
     2824
     2825              if (!stat (filename, &sb) && S_ISDIR (sb.st_mode))
     2826                removeEmptyFoldersAndJunkFiles (filename);
     2827              else if (isJunkFile (d->d_name))
     2828                tr_remove (filename);
     2829
     2830              tr_free (filename);
    27922831            }
    27932832        }
    2794         tr_remove (folder);
    2795         closedir (odir);
     2833
     2834      tr_remove (folder);
     2835      closedir (odir);
    27962836    }
    27972837}
     
    28092849deleteLocalData (tr_torrent * tor, tr_fileFunc func)
    28102850{
    2811     int i, n;
    2812     tr_file_index_t f;
    2813     char * base;
    2814     DIR * odir;
    2815     char * tmpdir = NULL;
    2816     tr_ptrArray files = TR_PTR_ARRAY_INIT;
    2817     tr_ptrArray folders = TR_PTR_ARRAY_INIT;
    2818     const void * const vstrcmp = strcmp;
    2819     const char * const top = tor->currentDir;
    2820 
    2821     /* if it's a magnet link, there's nothing to move... */
    2822     if (!tr_torrentHasMetadata (tor))
    2823         return;
    2824 
    2825     /***
    2826     ****  Move the local data to a new tmpdir
    2827     ***/
    2828 
    2829     base = tr_strdup_printf ("%s__XXXXXX", tr_torrentName (tor));
    2830     tmpdir = tr_buildPath (top, base, NULL);
    2831     tr_mkdtemp (tmpdir);
    2832     tr_free (base);
    2833 
    2834     for (f=0; f<tor->info.fileCount; ++f)
    2835     {
    2836         char * filename = tr_buildPath (top, tor->info.files[f].name, NULL);
    2837         if (!tr_fileExists (filename, NULL)) {
    2838                 char * partial = tr_torrentBuildPartial (tor, f);
    2839                 tr_free (filename);
    2840                 filename = tr_buildPath (top, partial, NULL);
    2841                 tr_free (partial);
    2842                 if (!tr_fileExists (filename, NULL)) {
    2843                         tr_free (filename);
    2844                         filename = NULL;
    2845                 }
    2846         }
    2847 
    2848         if (filename != NULL)
     2851  int i, n;
     2852  tr_file_index_t f;
     2853  char * base;
     2854  DIR * odir;
     2855  char * tmpdir = NULL;
     2856  tr_ptrArray files = TR_PTR_ARRAY_INIT;
     2857  tr_ptrArray folders = TR_PTR_ARRAY_INIT;
     2858  const void * const vstrcmp = strcmp;
     2859  const char * const top = tor->currentDir;
     2860
     2861  /* if it's a magnet link, there's nothing to move... */
     2862  if (!tr_torrentHasMetadata (tor))
     2863    return;
     2864
     2865  /***
     2866  ****  Move the local data to a new tmpdir
     2867  ***/
     2868
     2869  base = tr_strdup_printf ("%s__XXXXXX", tr_torrentName (tor));
     2870  tmpdir = tr_buildPath (top, base, NULL);
     2871  tr_mkdtemp (tmpdir);
     2872  tr_free (base);
     2873
     2874  for (f=0; f<tor->info.fileCount; ++f)
     2875    {
     2876      char * filename;
     2877
     2878      /* try to find the file, looking in the partial and download dirs */
     2879      filename = tr_buildPath (top, tor->info.files[f].name, NULL);
     2880      if (!tr_fileExists (filename, NULL))
    28492881        {
    2850             char * target = tr_buildPath (tmpdir, tor->info.files[f].name, NULL);
    2851             tr_moveFile (filename, target, NULL);
    2852             tr_ptrArrayAppend (&files, target);
    2853             tr_free (filename);
    2854         }
    2855     }