Changeset 13863


Ignore:
Timestamp:
Jan 24, 2013, 11:59:52 PM (8 years ago)
Author:
jordan
Message:

(libT) copyediting: modify more files to the new indentation/whitespace formatting

Location:
trunk/libtransmission
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/bandwidth.c

    r13625 r13863  
    2222
    2323#define dbgmsg(...) \
    24     do { \
    25         if (tr_deepLoggingIsActive ()) \
    26             tr_deepLog (__FILE__, __LINE__, NULL, __VA_ARGS__); \
    27     } while (0)
     24  do \
     25    { \
     26      if (tr_deepLoggingIsActive ()) \
     27        tr_deepLog (__FILE__, __LINE__, NULL, __VA_ARGS__); \
     28    } \
     29  while (0)
    2830
    2931/***
     
    3436getSpeed_Bps (const struct bratecontrol * r, unsigned int interval_msec, uint64_t now)
    3537{
    36     if (!now)
    37         now = tr_time_msec ();
    38 
    39     if (now != r->cache_time)
    40     {
    41         int i = r->newest;
    42         uint64_t bytes = 0;
    43         const uint64_t cutoff = now - interval_msec;
    44         struct bratecontrol * rvolatile = (struct bratecontrol*) r;
    45 
    46         for (;;)
     38  if (!now)
     39    now = tr_time_msec ();
     40
     41  if (now != r->cache_time)
     42    {
     43      int i = r->newest;
     44      uint64_t bytes = 0;
     45      const uint64_t cutoff = now - interval_msec;
     46      struct bratecontrol * rvolatile = (struct bratecontrol*) r;
     47
     48      for (;;)
    4749        {
    48             if (r->transfers[i].date <= cutoff)
    49                 break;
    50 
    51             bytes += r->transfers[i].size;
    52 
    53             if (--i == -1) i = HISTORY_SIZE - 1; /* circular history */
    54             if (i == r->newest) break; /* we've come all the way around */
     50          if (r->transfers[i].date <= cutoff)
     51            break;
     52
     53          bytes += r->transfers[i].size;
     54
     55          if (--i == -1)
     56            i = HISTORY_SIZE - 1; /* circular history */
     57
     58          if (i == r->newest)
     59            break; /* we've come all the way around */
    5560        }
    5661
    57         rvolatile->cache_val = (unsigned int)((bytes * 1000u) / interval_msec);
    58         rvolatile->cache_time = now;
    59     }
    60 
    61     return r->cache_val;
     62      rvolatile->cache_val = (unsigned int)((bytes * 1000u) / interval_msec);
     63      rvolatile->cache_time = now;
     64    }
     65
     66  return r->cache_val;
    6267}
    6368
     
    6570bytesUsed (const uint64_t now, struct bratecontrol * r, size_t size)
    6671{
    67     if (r->transfers[r->newest].date + GRANULARITY_MSEC >= now)
    68         r->transfers[r->newest].size += size;
    69     else
    70     {
    71         if (++r->newest == HISTORY_SIZE) r->newest = 0;
    72         r->transfers[r->newest].date = now;
    73         r->transfers[r->newest].size = size;
    74     }
    75 
    76     /* invalidate cache_val*/
    77     r->cache_time = 0;
     72  if (r->transfers[r->newest].date + GRANULARITY_MSEC >= now)
     73    {
     74      r->transfers[r->newest].size += size;
     75    }
     76  else
     77    {
     78      if (++r->newest == HISTORY_SIZE)
     79        r->newest = 0;
     80      r->transfers[r->newest].date = now;
     81      r->transfers[r->newest].size = size;
     82    }
     83
     84  /* invalidate cache_val*/
     85  r->cache_time = 0;
    7886}
    7987
     
    8694compareBandwidth (const void * va, const void * vb)
    8795{
    88     const tr_bandwidth * a = va;
    89     const tr_bandwidth * b = vb;
    90     return a->uniqueKey - b->uniqueKey;
     96  const tr_bandwidth * a = va;
     97  const tr_bandwidth * b = vb;
     98  return a->uniqueKey - b->uniqueKey;
    9199}
    92100
     
    98106tr_bandwidthConstruct (tr_bandwidth * b, tr_session * session, tr_bandwidth * parent)
    99107{
    100     static unsigned int uniqueKey = 0;
    101 
    102     b->session = session;
    103     b->children = TR_PTR_ARRAY_INIT;
    104     b->magicNumber = BANDWIDTH_MAGIC_NUMBER;
    105     b->uniqueKey = uniqueKey++;
    106     b->band[TR_UP].honorParentLimits = true;
    107     b->band[TR_DOWN].honorParentLimits = true;
    108     tr_bandwidthSetParent (b, parent);
     108  static unsigned int uniqueKey = 0;
     109
     110  b->session = session;
     111  b->children = TR_PTR_ARRAY_INIT;
     112  b->magicNumber = BANDWIDTH_MAGIC_NUMBER;
     113  b->uniqueKey = uniqueKey++;
     114  b->band[TR_UP].honorParentLimits = true;
     115  b->band[TR_DOWN].honorParentLimits = true;
     116  tr_bandwidthSetParent (b, parent);
    109117}
    110118
     
    112120tr_bandwidthDestruct (tr_bandwidth * b)
    113121{
    114     assert (tr_isBandwidth (b));
    115 
    116     tr_bandwidthSetParent (b, NULL);
    117     tr_ptrArrayDestruct (&b->children, NULL);
    118 
    119     memset (b, ~0, sizeof (tr_bandwidth));
     122  assert (tr_isBandwidth (b));
     123
     124  tr_bandwidthSetParent (b, NULL);
     125  tr_ptrArrayDestruct (&b->children, NULL);
     126
     127  memset (b, ~0, sizeof (tr_bandwidth));
    120128}
    121129
     
    128136                       tr_bandwidth  * parent)
    129137{
    130     assert (tr_isBandwidth (b));
    131     assert (b != parent);
    132 
    133     if (b->parent)
    134     {
    135         void * removed;
    136 
    137         assert (tr_isBandwidth (b->parent));
    138 
    139         removed = tr_ptrArrayRemoveSorted (&b->parent->children, b, compareBandwidth);
    140         assert (removed == b);
    141         assert (tr_ptrArrayFindSorted (&b->parent->children, b, compareBandwidth) == NULL);
    142 
    143         b->parent = NULL;
    144     }
    145 
    146     if (parent)
    147     {
    148         assert (tr_isBandwidth (parent));
    149         assert (parent->parent != b);
    150 
    151         assert (tr_ptrArrayFindSorted (&parent->children, b, compareBandwidth) == NULL);
    152         tr_ptrArrayInsertSorted (&parent->children, b, compareBandwidth);
    153         assert (tr_ptrArrayFindSorted (&parent->children, b, compareBandwidth) == b);
    154         b->parent = parent;
     138  assert (tr_isBandwidth (b));
     139  assert (b != parent);
     140
     141  if (b->parent)
     142    {
     143      void * removed;
     144
     145      assert (tr_isBandwidth (b->parent));
     146
     147      removed = tr_ptrArrayRemoveSorted (&b->parent->children, b, compareBandwidth);
     148      assert (removed == b);
     149      assert (tr_ptrArrayFindSorted (&b->parent->children, b, compareBandwidth) == NULL);
     150
     151      b->parent = NULL;
     152    }
     153
     154  if (parent)
     155    {
     156      assert (tr_isBandwidth (parent));
     157      assert (parent->parent != b);
     158
     159      assert (tr_ptrArrayFindSorted (&parent->children, b, compareBandwidth) == NULL);
     160      tr_ptrArrayInsertSorted (&parent->children, b, compareBandwidth);
     161      assert (tr_ptrArrayFindSorted (&parent->children, b, compareBandwidth) == b);
     162      b->parent = parent;
    155163    }
    156164}
     
    167175                   tr_ptrArray   * peer_pool)
    168176{
    169     const tr_priority_t priority = MAX (parent_priority, b->priority);
    170 
    171     assert (tr_isBandwidth (b));
    172     assert (tr_isDirection (dir));
    173 
    174     /* set the available bandwidth */
    175     if (b->band[dir].isLimited)
    176     {
    177         const uint64_t nextPulseSpeed = b->band[dir].desiredSpeed_Bps;
    178         b->band[dir].bytesLeft = (unsigned int)(nextPulseSpeed * period_msec) / 1000u;
    179     }
    180 
    181     /* add this bandwidth's peer, if any, to the peer pool */
    182     if (b->peer != NULL) {
    183         b->peer->priority = priority;
    184         tr_ptrArrayAppend (peer_pool, b->peer);
    185     }
    186 
    187     /* traverse & repeat for the subtree */
    188     if (1) {
    189         int i;
    190         struct tr_bandwidth ** children = (struct tr_bandwidth**) tr_ptrArrayBase (&b->children);
    191         const int n = tr_ptrArraySize (&b->children);
    192         for (i=0; i<n; ++i)
    193             allocateBandwidth (children[i], priority, dir, period_msec, peer_pool);
     177  const tr_priority_t priority = MAX (parent_priority, b->priority);
     178
     179  assert (tr_isBandwidth (b));
     180  assert (tr_isDirection (dir));
     181
     182  /* set the available bandwidth */
     183  if (b->band[dir].isLimited)
     184    {
     185      const uint64_t nextPulseSpeed = b->band[dir].desiredSpeed_Bps;
     186      b->band[dir].bytesLeft = (unsigned int)(nextPulseSpeed * period_msec) / 1000u;
     187    }
     188
     189  /* add this bandwidth's peer, if any, to the peer pool */
     190  if (b->peer != NULL)
     191    {
     192      b->peer->priority = priority;
     193      tr_ptrArrayAppend (peer_pool, b->peer);
     194    }
     195
     196  /* traverse & repeat for the subtree */
     197  if (1)
     198    {
     199      int i;
     200      struct tr_bandwidth ** children = (struct tr_bandwidth**) tr_ptrArrayBase (&b->children);
     201      const int n = tr_ptrArraySize (&b->children);
     202      for (i=0; i<n; ++i)
     203        allocateBandwidth (children[i], priority, dir, period_msec, peer_pool);
    194204    }
    195205}
     
    198208phaseOne (tr_ptrArray * peerArray, tr_direction dir)
    199209{
    200     int n;
    201     int peerCount = tr_ptrArraySize (peerArray);
    202     struct tr_peerIo ** peers = (struct tr_peerIo**) tr_ptrArrayBase (peerArray);
    203 
    204     /* First phase of IO. Tries to distribute bandwidth fairly to keep faster
    205      * peers from starving the others. Loop through the peers, giving each a
    206      * small chunk of bandwidth. Keep looping until we run out of bandwidth
    207      * and/or peers that can use it */
    208     n = peerCount;
    209     dbgmsg ("%d peers to go round-robin for %s", n, (dir==TR_UP?"upload":"download"));
    210     while (n > 0)
    211     {
    212         const int i = tr_cryptoWeakRandInt (n); /* pick a peer at random */
    213 
    214         /* value of 3000 bytes chosen so that when using uTP we'll send a full-size
    215          * frame right away and leave enough buffered data for the next frame to go
    216          * out in a timely manner. */
    217         const size_t increment = 3000;
    218 
    219         const int bytesUsed = tr_peerIoFlush (peers[i], dir, increment);
    220 
    221         dbgmsg ("peer #%d of %d used %d bytes in this pass", i, n, bytesUsed);
    222 
    223         if (bytesUsed != (int)increment) {
    224             /* peer is done writing for now; move it to the end of the list */
    225             tr_peerIo * pio = peers[i];
    226             peers[i] = peers[n-1];
    227             peers[n-1] = pio;
    228             --n;
     210  int n;
     211  int peerCount = tr_ptrArraySize (peerArray);
     212  struct tr_peerIo ** peers = (struct tr_peerIo**) tr_ptrArrayBase (peerArray);
     213
     214  /* First phase of IO. Tries to distribute bandwidth fairly to keep faster
     215   * peers from starving the others. Loop through the peers, giving each a
     216   * small chunk of bandwidth. Keep looping until we run out of bandwidth
     217   * and/or peers that can use it */
     218  n = peerCount;
     219  dbgmsg ("%d peers to go round-robin for %s", n, (dir==TR_UP?"upload":"download"));
     220  while (n > 0)
     221    {
     222      const int i = tr_cryptoWeakRandInt (n); /* pick a peer at random */
     223
     224      /* value of 3000 bytes chosen so that when using uTP we'll send a full-size
     225       * frame right away and leave enough buffered data for the next frame to go
     226       * out in a timely manner. */
     227      const size_t increment = 3000;
     228
     229      const int bytesUsed = tr_peerIoFlush (peers[i], dir, increment);
     230
     231      dbgmsg ("peer #%d of %d used %d bytes in this pass", i, n, bytesUsed);
     232
     233      if (bytesUsed != (int)increment)
     234        {
     235          /* peer is done writing for now; move it to the end of the list */
     236          tr_peerIo * pio = peers[i];
     237          peers[i] = peers[n-1];
     238          peers[n-1] = pio;
     239          --n;
    229240        }
    230241    }
     
    236247                      unsigned int    period_msec)
    237248{
    238     int i, peerCount;
    239     tr_ptrArray tmp = TR_PTR_ARRAY_INIT;
    240     tr_ptrArray low = TR_PTR_ARRAY_INIT;
    241     tr_ptrArray high = TR_PTR_ARRAY_INIT;
    242     tr_ptrArray normal = TR_PTR_ARRAY_INIT;
    243     struct tr_peerIo ** peers;
    244 
    245     /* allocateBandwidth () is a helper function with two purposes:
    246      * 1. allocate bandwidth to b and its subtree
    247      * 2. accumulate an array of all the peerIos from b and its subtree. */
    248     allocateBandwidth (b, TR_PRI_LOW, dir, period_msec, &tmp);
    249     peers = (struct tr_peerIo**) tr_ptrArrayBase (&tmp);
    250     peerCount = tr_ptrArraySize (&tmp);
    251 
    252     for (i=0; i<peerCount; ++i)
    253     {
    254         tr_peerIo * io = peers[i];
    255         tr_peerIoRef (io);
    256 
    257         tr_peerIoFlushOutgoingProtocolMsgs (io);
    258 
    259         switch (io->priority) {
    260             case TR_PRI_HIGH:   tr_ptrArrayAppend (&high,   io); /* fall through */
    261             case TR_PRI_NORMAL: tr_ptrArrayAppend (&normal, io); /* fall through */
    262             default:            tr_ptrArrayAppend (&low,    io);
     249  int i, peerCount;
     250  tr_ptrArray tmp = TR_PTR_ARRAY_INIT;
     251  tr_ptrArray low = TR_PTR_ARRAY_INIT;
     252  tr_ptrArray high = TR_PTR_ARRAY_INIT;
     253  tr_ptrArray normal = TR_PTR_ARRAY_INIT;
     254  struct tr_peerIo ** peers;
     255
     256  /* allocateBandwidth () is a helper function with two purposes:
     257   * 1. allocate bandwidth to b and its subtree
     258   * 2. accumulate an array of all the peerIos from b and its subtree. */
     259  allocateBandwidth (b, TR_PRI_LOW, dir, period_msec, &tmp);
     260  peers = (struct tr_peerIo**) tr_ptrArrayBase (&tmp);
     261  peerCount = tr_ptrArraySize (&tmp);
     262
     263  for (i=0; i<peerCount; ++i)
     264    {
     265      tr_peerIo * io = peers[i];
     266      tr_peerIoRef (io);
     267
     268      tr_peerIoFlushOutgoingProtocolMsgs (io);
     269
     270      switch (io->priority)
     271        {
     272          case TR_PRI_HIGH:   tr_ptrArrayAppend (&high,   io); /* fall through */
     273          case TR_PRI_NORMAL: tr_ptrArrayAppend (&normal, io); /* fall through */
     274          default:            tr_ptrArrayAppend (&low,    io);
    263275        }
    264276    }
    265277
    266     /* First phase of IO. Tries to distribute bandwidth fairly to keep faster
    267      * peers from starving the others. Loop through the peers, giving each a
    268      * small chunk of bandwidth. Keep looping until we run out of bandwidth
    269      * and/or peers that can use it */
    270     phaseOne (&high, dir);
    271     phaseOne (&normal, dir);
    272     phaseOne (&low, dir);
    273 
    274     /* Second phase of IO. To help us scale in high bandwidth situations,
    275      * enable on-demand IO for peers with bandwidth left to burn.
    276      * This on-demand IO is enabled until (1) the peer runs out of bandwidth,
    277      * or (2) the next tr_bandwidthAllocate () call, when we start over again. */
    278     for (i=0; i<peerCount; ++i)
    279         tr_peerIoSetEnabled (peers[i], dir, tr_peerIoHasBandwidthLeft (peers[i], dir));
    280 
    281     for (i=0; i<peerCount; ++i)
    282         tr_peerIoUnref (peers[i]);
    283 
    284     /* cleanup */
    285     tr_ptrArrayDestruct (&normal, NULL);
    286     tr_ptrArrayDestruct (&high, NULL);
    287     tr_ptrArrayDestruct (&low, NULL);
    288     tr_ptrArrayDestruct (&tmp, NULL);
     278  /* First phase of IO. Tries to distribute bandwidth fairly to keep faster
     279   * peers from starving the others. Loop through the peers, giving each a
     280   * small chunk of bandwidth. Keep looping until we run out of bandwidth
     281   * and/or peers that can use it */
     282  phaseOne (&high, dir);
     283  phaseOne (&normal, dir);
     284  phaseOne (&low, dir);
     285
     286  /* Second phase of IO. To help us scale in high bandwidth situations,
     287   * enable on-demand IO for peers with bandwidth left to burn.
     288   * This on-demand IO is enabled until (1) the peer runs out of bandwidth,
     289   * or (2) the next tr_bandwidthAllocate () call, when we start over again. */
     290  for (i=0; i<peerCount; ++i)
     291    tr_peerIoSetEnabled (peers[i], dir, tr_peerIoHasBandwidthLeft (peers[i], dir));
     292
     293  for (i=0; i<peerCount; ++i)
     294    tr_peerIoUnref (peers[i]);
     295
     296  /* cleanup */
     297  tr_ptrArrayDestruct (&normal, NULL);
     298  tr_ptrArrayDestruct (&high, NULL);
     299  tr_ptrArrayDestruct (&low, NULL);
     300  tr_ptrArrayDestruct (&tmp, NULL);
    289301}
    290302
     
    292304tr_bandwidthSetPeer (tr_bandwidth * b, tr_peerIo * peer)
    293305{
    294     assert (tr_isBandwidth (b));
    295     assert ((peer == NULL) || tr_isPeerIo (peer));
    296 
    297     b->peer = peer;
     306  assert (tr_isBandwidth (b));
     307  assert ((peer == NULL) || tr_isPeerIo (peer));
     308
     309  b->peer = peer;
    298310}
    299311
     
    308320                unsigned int          byteCount)
    309321{
    310     assert (tr_isBandwidth (b));
    311     assert (tr_isDirection (dir));
    312 
    313     if (b)
    314     {
    315         if (b->band[dir].isLimited)
     322  assert (tr_isBandwidth (b));
     323  assert (tr_isDirection (dir));
     324
     325  if (b)
     326    {
     327      if (b->band[dir].isLimited)
    316328        {
    317             byteCount = MIN (byteCount, b->band[dir].bytesLeft);
    318 
    319             /* if we're getting close to exceeding the speed limit,
    320              * clamp down harder on the bytes available */
    321             if (byteCount > 0)
     329          byteCount = MIN (byteCount, b->band[dir].bytesLeft);
     330
     331          /* if we're getting close to exceeding the speed limit,
     332           * clamp down harder on the bytes available */
     333          if (byteCount > 0)
    322334            {
    323                 double current;
    324                 double desired;
    325                 double r;
    326 
    327                 if (now == 0)
    328                     now = tr_time_msec ();
    329 
    330                 current = tr_bandwidthGetRawSpeed_Bps (b, now, TR_DOWN);
    331                 desired = tr_bandwidthGetDesiredSpeed_Bps (b, TR_DOWN);
    332                 r = desired >= 1 ? current / desired : 0;
    333 
    334                      if (r > 1.0) byteCount = 0;
    335                 else if (r > 0.9) byteCount *= 0.8;
    336                 else if (r > 0.8) byteCount *= 0.9;
     335              double current;
     336              double desired;
     337              double r;
     338
     339              if (now == 0)
     340                now = tr_time_msec ();
     341
     342              current = tr_bandwidthGetRawSpeed_Bps (b, now, TR_DOWN);
     343              desired = tr_bandwidthGetDesiredSpeed_Bps (b, TR_DOWN);
     344              r = desired >= 1 ? current / desired : 0;
     345
     346                   if (r > 1.0) byteCount = 0;
     347              else if (r > 0.9) byteCount *= 0.8;
     348              else if (r > 0.8) byteCount *= 0.9;
    337349            }
    338350        }
    339351
    340         if (b->parent && b->band[dir].honorParentLimits && (byteCount > 0))
    341             byteCount = bandwidthClamp (b->parent, now, dir, byteCount);
    342     }
    343 
    344     return byteCount;
     352      if (b->parent && b->band[dir].honorParentLimits && (byteCount > 0))
     353        byteCount = bandwidthClamp (b->parent, now, dir, byteCount);
     354    }
     355
     356  return byteCount;
    345357}
    346358unsigned int
     
    349361                   unsigned int          byteCount)
    350362{
    351     return bandwidthClamp (b, 0, dir, byteCount);
     363  return bandwidthClamp (b, 0, dir, byteCount);
    352364}
    353365
     
    356368tr_bandwidthGetRawSpeed_Bps (const tr_bandwidth * b, const uint64_t now, const tr_direction dir)
    357369{
    358     assert (tr_isBandwidth (b));
    359     assert (tr_isDirection (dir));
    360 
    361     return getSpeed_Bps (&b->band[dir].raw, HISTORY_MSEC, now);
     370  assert (tr_isBandwidth (b));
     371  assert (tr_isDirection (dir));
     372
     373  return getSpeed_Bps (&b->band[dir].raw, HISTORY_MSEC, now);
    362374}
    363375
     
    365377tr_bandwidthGetPieceSpeed_Bps (const tr_bandwidth * b, const uint64_t now, const tr_direction dir)
    366378{
    367     assert (tr_isBandwidth (b));
    368     assert (tr_isDirection (dir));
    369 
    370     return getSpeed_Bps (&b->band[dir].piece, HISTORY_MSEC, now);
     379  assert (tr_isBandwidth (b));
     380  assert (tr_isDirection (dir));
     381
     382  return getSpeed_Bps (&b->band[dir].piece, HISTORY_MSEC, now);
    371383}
    372384
     
    375387                  tr_direction    dir,
    376388                  size_t          byteCount,
    377                   bool         isPieceData,
     389                  bool            isPieceData,
    378390                  uint64_t        now)
    379391{
    380     struct tr_band * band;
    381 
    382     assert (tr_isBandwidth (b));
    383     assert (tr_isDirection (dir));
    384 
    385     band = &b->band[dir];
    386 
    387     if (band->isLimited && isPieceData)
    388         band->bytesLeft -= MIN (band->bytesLeft, byteCount);
     392  struct tr_band * band;
     393
     394  assert (tr_isBandwidth (b));
     395  assert (tr_isDirection (dir));
     396
     397  band = &b->band[dir];
     398
     399  if (band->isLimited && isPieceData)
     400    band->bytesLeft -= MIN (band->bytesLeft, byteCount);
    389401
    390402#ifdef DEBUG_DIRECTION
     
    394406#endif
    395407
    396     bytesUsed (now, &band->raw, byteCount);
    397 
    398     if (isPieceData)
    399         bytesUsed (now, &band->piece, byteCount);
    400 
    401     if (b->parent != NULL)
    402         tr_bandwidthUsed (b->parent, dir, byteCount, isPieceData, now);
    403 }
     408  bytesUsed (now, &band->raw, byteCount);
     409
     410  if (isPieceData)
     411    bytesUsed (now, &band->piece, byteCount);
     412
     413  if (b->parent != NULL)
     414    tr_bandwidthUsed (b->parent, dir, byteCount, isPieceData, now);
     415}
  • trunk/libtransmission/crypto.c

    r13625 r13863  
    3838tr_sha1 (uint8_t * setme, const void * content1, int content1_len, ...)
    3939{
    40     va_list vl;
    41     SHA_CTX sha;
    42     const void * content;
    43 
    44     SHA1_Init (&sha);
    45     SHA1_Update (&sha, content1, content1_len);
    46 
    47     va_start (vl, content1_len);
    48     while ((content = va_arg (vl, const void*)))
    49         SHA1_Update (&sha, content, va_arg (vl, int));
    50     va_end (vl);
    51 
    52     SHA1_Final (setme, &sha);
     40  va_list vl;
     41  SHA_CTX sha;
     42  const void * content;
     43
     44  SHA1_Init (&sha);
     45  SHA1_Update (&sha, content1, content1_len);
     46
     47  va_start (vl, content1_len);
     48  while ((content = va_arg (vl, const void*)))
     49    SHA1_Update (&sha, content, va_arg (vl, int));
     50  va_end (vl);
     51
     52  SHA1_Final (setme, &sha);
    5353}
    5454
     
    6666static const uint8_t dh_P[PRIME_LEN] =
    6767{
    68     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
    69     0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
    70     0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
    71     0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
    72     0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
    73     0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
    74     0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
    75     0xA6, 0x3A, 0x36, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x05, 0x63,
     68  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
     69  0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
     70  0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
     71  0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
     72  0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
     73  0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
     74  0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
     75  0xA6, 0x3A, 0x36, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x05, 0x63,
    7676};
    7777
     
    8383
    8484#define logErrorFromSSL(...) \
    85     do { \
    86         if (tr_msgLoggingIsActive (TR_MSG_ERR)) { \
    87             char buf[512]; \
    88             ERR_error_string_n (ERR_get_error (), buf, sizeof (buf)); \
    89             tr_msg (__FILE__, __LINE__, TR_MSG_ERR, MY_NAME, "%s", buf); \
    90         } \
    91     } while (0)
     85  do { \
     86    if (tr_msgLoggingIsActive (TR_MSG_ERR)) { \
     87      char buf[512]; \
     88      ERR_error_string_n (ERR_get_error (), buf, sizeof (buf)); \
     89      tr_msg (__FILE__, __LINE__, TR_MSG_ERR, MY_NAME, "%s", buf); \
     90    } \
     91  } while (0)
    9292
    9393static void
    9494ensureKeyExists (tr_crypto * crypto)
    9595{
    96     if (crypto->dh == NULL)
    97     {
    98         int len, offset;
    99         DH * dh = DH_new ();
    100 
    101         dh->p = BN_bin2bn (dh_P, sizeof (dh_P), NULL);
    102         if (dh->p == NULL)
     96  if (crypto->dh == NULL)
     97    {
     98      int len, offset;
     99      DH * dh = DH_new ();
     100
     101      dh->p = BN_bin2bn (dh_P, sizeof (dh_P), NULL);
     102      if (dh->p == NULL)
     103        logErrorFromSSL ();
     104
     105      dh->g = BN_bin2bn (dh_G, sizeof (dh_G), NULL);
     106      if (dh->g == NULL)
     107        logErrorFromSSL ();
     108
     109      /* private DH value: strong random BN of DH_PRIVKEY_LEN*8 bits */
     110      dh->priv_key = BN_new ();
     111      do
     112        {
     113          if (BN_rand (dh->priv_key, DH_PRIVKEY_LEN * 8, -1, 0) != 1)
    103114            logErrorFromSSL ();
    104 
    105         dh->g = BN_bin2bn (dh_G, sizeof (dh_G), NULL);
    106         if (dh->g == NULL)
    107             logErrorFromSSL ();
    108 
    109         /* private DH value: strong random BN of DH_PRIVKEY_LEN*8 bits */
    110         dh->priv_key = BN_new ();
    111         do {
    112             if (BN_rand (dh->priv_key, DH_PRIVKEY_LEN * 8, -1, 0) != 1)
    113                 logErrorFromSSL ();
    114         } while (BN_num_bits (dh->priv_key) < DH_PRIVKEY_LEN_MIN * 8);
    115 
    116         if (!DH_generate_key (dh))
    117             logErrorFromSSL ();
    118 
    119         /* DH can generate key sizes that are smaller than the size of
    120            P with exponentially decreasing probability, in which case
    121            the msb's of myPublicKey need to be zeroed appropriately. */
    122         len = BN_num_bytes (dh->pub_key);
    123         offset = KEY_LEN - len;
    124         assert (len <= KEY_LEN);
    125         memset (crypto->myPublicKey, 0, offset);
    126         BN_bn2bin (dh->pub_key, crypto->myPublicKey + offset);
    127 
    128         crypto->dh = dh;
     115        }
     116      while (BN_num_bits (dh->priv_key) < DH_PRIVKEY_LEN_MIN * 8);
     117
     118      if (!DH_generate_key (dh))
     119        logErrorFromSSL ();
     120
     121      /* DH can generate key sizes that are smaller than the size of
     122         P with exponentially decreasing probability, in which case
     123         the msb's of myPublicKey need to be zeroed appropriately. */
     124      len = BN_num_bytes (dh->pub_key);
     125      offset = KEY_LEN - len;
     126      assert (len <= KEY_LEN);
     127      memset (crypto->myPublicKey, 0, offset);
     128      BN_bn2bin (dh->pub_key, crypto->myPublicKey + offset);
     129
     130      crypto->dh = dh;
    129131    }
    130132}
     
    133135tr_cryptoConstruct (tr_crypto * crypto, const uint8_t * torrentHash, bool isIncoming)
    134136{
    135     memset (crypto, 0, sizeof (tr_crypto));
    136 
    137     crypto->dh = NULL;
    138     crypto->isIncoming = isIncoming;
    139     tr_cryptoSetTorrentHash (crypto, torrentHash);
     137  memset (crypto, 0, sizeof (tr_crypto));
     138
     139  crypto->dh = NULL;
     140  crypto->isIncoming = isIncoming;
     141  tr_cryptoSetTorrentHash (crypto, torrentHash);
    140142}
    141143
     
    143145tr_cryptoDestruct (tr_crypto * crypto)
    144146{
    145     if (crypto->dh != NULL)
    146         DH_free (crypto->dh);
     147  if (crypto->dh != NULL)
     148    DH_free (crypto->dh);
    147149}
    148150
     
    155157                        const uint8_t * peerPublicKey)
    156158{
    157     int      len;
    158     uint8_t  secret[KEY_LEN];
    159     BIGNUM * bn = BN_bin2bn (peerPublicKey, KEY_LEN, NULL);
    160     DH *     dh;
    161 
    162     ensureKeyExists (crypto);
    163     dh = crypto->dh;
    164 
    165     assert (DH_size (dh) == KEY_LEN);
    166 
    167     len = DH_compute_key (secret, bn, dh);
    168     if (len == -1)
    169         logErrorFromSSL ();
    170     else {
    171         int offset;
    172         assert (len <= KEY_LEN);
    173         offset = KEY_LEN - len;
    174         memset (crypto->mySecret, 0, offset);
    175         memcpy (crypto->mySecret + offset, secret, len);
    176         crypto->mySecretIsSet = 1;
    177     }
    178 
    179     BN_free (bn);
    180     return crypto->mySecret;
     159  DH * dh;
     160  int len;
     161  uint8_t secret[KEY_LEN];
     162  BIGNUM * bn = BN_bin2bn (peerPublicKey, KEY_LEN, NULL);
     163
     164  ensureKeyExists (crypto);
     165  dh = crypto->dh;
     166
     167  assert (DH_size (dh) == KEY_LEN);
     168
     169  len = DH_compute_key (secret, bn, dh);
     170  if (len == -1)
     171    {
     172      logErrorFromSSL ();
     173    }
     174  else
     175    {
     176      int offset;
     177      assert (len <= KEY_LEN);
     178      offset = KEY_LEN - len;
     179      memset (crypto->mySecret, 0, offset);
     180      memcpy (crypto->mySecret + offset, secret, len);
     181      crypto->mySecretIsSet = 1;
     182    }
     183
     184  BN_free (bn);
     185  return crypto->mySecret;
    181186}
    182187
    183188const uint8_t*
    184189tr_cryptoGetMyPublicKey (const tr_crypto * crypto,
    185                          int *            setme_len)
    186 {
    187     ensureKeyExists ((tr_crypto *) crypto);
    188     *setme_len = KEY_LEN;
    189     return crypto->myPublicKey;
     190                         int             * setme_len)
     191{
     192  ensureKeyExists ((tr_crypto *) crypto);
     193  *setme_len = KEY_LEN;
     194  return crypto->myPublicKey;
    190195}
    191196
     
    195200
    196201static void
    197 initRC4 (tr_crypto * crypto,
    198          RC4_KEY *    setme,
     202initRC4 (tr_crypto  * crypto,
     203         RC4_KEY    * setme,
    199204         const char * key)
    200205{
    201     SHA_CTX sha;
    202     uint8_t buf[SHA_DIGEST_LENGTH];
    203 
    204     assert (crypto->torrentHashIsSet);
    205     assert (crypto->mySecretIsSet);
    206 
    207     if (SHA1_Init (&sha)
    208         && SHA1_Update (&sha, key, 4)
    209         && SHA1_Update (&sha, crypto->mySecret, KEY_LEN)
    210         && SHA1_Update (&sha, crypto->torrentHash, SHA_DIGEST_LENGTH)
    211         && SHA1_Final (buf, &sha))
    212     {
    213         RC4_set_key (setme, SHA_DIGEST_LENGTH, buf);
    214     }
    215     else
    216     {
    217         logErrorFromSSL ();
     206  SHA_CTX sha;
     207  uint8_t buf[SHA_DIGEST_LENGTH];
     208
     209  assert (crypto->torrentHashIsSet);
     210  assert (crypto->mySecretIsSet);
     211
     212  if (SHA1_Init (&sha)
     213      && SHA1_Update (&sha, key, 4)
     214      && SHA1_Update (&sha, crypto->mySecret, KEY_LEN)
     215      && SHA1_Update (&sha, crypto->torrentHash, SHA_DIGEST_LENGTH)
     216      && SHA1_Final (buf, &sha))
     217    {
     218      RC4_set_key (setme, SHA_DIGEST_LENGTH, buf);
     219    }
     220  else
     221    {
     222      logErrorFromSSL ();
    218223    }
    219224}
     
    222227tr_cryptoDecryptInit (tr_crypto * crypto)
    223228{
    224     unsigned char discard[1024];
    225     const char * txt = crypto->isIncoming ? "keyA" : "keyB";
    226 
    227     initRC4 (crypto, &crypto->dec_key, txt);
    228     RC4 (&crypto->dec_key, sizeof (discard), discard, discard);
    229 }
    230 
    231 void
    232 tr_cryptoDecrypt (tr_crypto * crypto,
     229  unsigned char discard[1024];
     230  const char * txt = crypto->isIncoming ? "keyA" : "keyB";
     231
     232  initRC4 (crypto, &crypto->dec_key, txt);
     233  RC4 (&crypto->dec_key, sizeof (discard), discard, discard);
     234}
     235
     236void
     237tr_cryptoDecrypt (tr_crypto  * crypto,
    233238                  size_t       buf_len,
    234239                  const void * buf_in,
    235                   void *      buf_out)
    236 {
    237     RC4 (&crypto->dec_key, buf_len,
     240                  void       * buf_out)
     241{
     242  RC4 (&crypto->dec_key, buf_len,
    238243       (const unsigned char*)buf_in,
    239244       (unsigned char*)buf_out);
     
    243248tr_cryptoEncryptInit (tr_crypto * crypto)
    244249{
    245     unsigned char discard[1024];
    246     const char * txt = crypto->isIncoming ? "keyB" : "keyA";
    247 
    248     initRC4 (crypto, &crypto->enc_key, txt);
    249     RC4 (&crypto->enc_key, sizeof (discard), discard, discard);
    250 }
    251 
    252 void
    253 tr_cryptoEncrypt (tr_crypto * crypto,
     250  unsigned char discard[1024];
     251  const char * txt = crypto->isIncoming ? "keyB" : "keyA";
     252
     253  initRC4 (crypto, &crypto->enc_key, txt);
     254  RC4 (&crypto->enc_key, sizeof (discard), discard, discard);
     255}
     256
     257void
     258tr_cryptoEncrypt (tr_crypto  * crypto,
    254259                  size_t       buf_len,
    255260                  const void * buf_in,
    256                   void *      buf_out)
    257 {
    258     RC4 (&crypto->enc_key, buf_len,
     261                  void       * buf_out)
     262{
     263  RC4 (&crypto->enc_key, buf_len,
    259264       (const unsigned char*)buf_in,
    260265       (unsigned char*)buf_out);
     
    266271
    267272void
    268 tr_cryptoSetTorrentHash (tr_crypto *    crypto,
     273tr_cryptoSetTorrentHash (tr_crypto     * crypto,
    269274                         const uint8_t * hash)
    270275{
    271     crypto->torrentHashIsSet = hash ? 1 : 0;
    272 
    273     if (hash)
    274         memcpy (crypto->torrentHash, hash, SHA_DIGEST_LENGTH);
    275     else
    276         memset (crypto->torrentHash, 0, SHA_DIGEST_LENGTH);
     276  crypto->torrentHashIsSet = hash ? 1 : 0;
     277
     278  if (hash)
     279    memcpy (crypto->torrentHash, hash, SHA_DIGEST_LENGTH);
     280  else
     281    memset (crypto->torrentHash, 0, SHA_DIGEST_LENGTH);
    277282}
    278283
     
    280285tr_cryptoGetTorrentHash (const tr_crypto * crypto)
    281286{
    282     assert (crypto);
    283     assert (crypto->torrentHashIsSet);
    284 
    285     return crypto->torrentHash;
     287  assert (crypto);
     288  assert (crypto->torrentHashIsSet);
     289
     290  return crypto->torrentHash;
    286291}
    287292
     
    289294tr_cryptoHasTorrentHash (const tr_crypto * crypto)
    290295{
    291     assert (crypto);
    292 
    293     return crypto->torrentHashIsSet ? 1 : 0;
     296  assert (crypto);
     297
     298  return crypto->torrentHashIsSet ? 1 : 0;
    294299}
    295300
     
    297302tr_cryptoRandInt (int upperBound)
    298303{
    299     int noise;
    300     int val;
    301 
    302     assert (upperBound > 0);
    303 
    304     if (RAND_pseudo_bytes ((unsigned char *) &noise, sizeof noise) >= 0)
    305     {
    306         val = abs (noise) % upperBound;
    307     }
    308     else /* fall back to a weaker implementation... */
    309     {
    310         val = tr_cryptoWeakRandInt (upperBound);
    311     }
    312 
    313     return val;
     304  int noise;
     305  int val;
     306
     307  assert (upperBound > 0);
     308
     309  if (RAND_pseudo_bytes ((unsigned char *) &noise, sizeof noise) >= 0)
     310    {
     311      val = abs (noise) % upperBound;
     312    }
     313  else /* fall back to a weaker implementation... */
     314    {
     315      val = tr_cryptoWeakRandInt (upperBound);
     316    }
     317
     318  return val;
    314319}
    315320
     
    317322tr_cryptoWeakRandInt (int upperBound)
    318323{
    319     static bool init = false;
    320 
    321     assert (upperBound > 0);
    322 
    323     if (!init)
    324     {
    325         srand (tr_time_msec ());
    326         init = true;
    327     }
    328 
    329     return rand () % upperBound;
     324  static bool init = false;
     325
     326  assert (upperBound > 0);
     327
     328  if (!init)
     329    {
     330      srand (tr_time_msec ());
     331      init = true;
     332    }
     333
     334  return rand () % upperBound;
    330335}
    331336
     
    333338tr_cryptoRandBuf (void * buf, size_t len)
    334339{
    335     if (RAND_pseudo_bytes ((unsigned char*)buf, len) != 1)
    336         logErrorFromSSL ();
     340  if (RAND_pseudo_bytes ((unsigned char*)buf, len) != 1)
     341    logErrorFromSSL ();
    337342}
    338343
     
    344349tr_ssha1 (const void * plaintext)
    345350{
    346     enum { saltval_len = 8,
    347            salter_len  = 64 };
    348     static const char * salter = "0123456789"
    349                                  "abcdefghijklmnopqrstuvwxyz"
    350                                  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    351                                  "./";
    352 
    353     size_t i;
    354     unsigned char salt[saltval_len];
    355     uint8_t sha[SHA_DIGEST_LENGTH];
    356     char buf[2*SHA_DIGEST_LENGTH + saltval_len + 2];
    357 
    358     tr_cryptoRandBuf (salt, saltval_len);
    359     for (i=0; i<saltval_len; ++i)
    360         salt[i] = salter[ salt[i] % salter_len ];
    361 
    362     tr_sha1 (sha, plaintext, strlen (plaintext), salt, saltval_len, NULL);
    363     tr_sha1_to_hex (&buf[1], sha);
    364     memcpy (&buf[1+2*SHA_DIGEST_LENGTH], &salt, saltval_len);
    365     buf[1+2*SHA_DIGEST_LENGTH + saltval_len] = '\0';
    366     buf[0] = '{'; /* signal that this is a hash. this makes saving/restoring
    367                      easier */
    368 
    369     return tr_strdup (&buf);
     351  enum { saltval_len = 8,
     352         salter_len  = 64 };
     353  static const char * salter = "0123456789"
     354                               "abcdefghijklmnopqrstuvwxyz"
     355                               "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
     356                               "./";
     357
     358  size_t i;
     359  unsigned char salt[saltval_len];
     360  uint8_t sha[SHA_DIGEST_LENGTH];
     361  char buf[2*SHA_DIGEST_LENGTH + saltval_len + 2];
     362
     363  tr_cryptoRandBuf (salt, saltval_len);
     364  for (i=0; i<saltval_len; ++i)
     365    salt[i] = salter[ salt[i] % salter_len ];
     366
     367  tr_sha1 (sha, plaintext, strlen (plaintext), salt, saltval_len, NULL);
     368  tr_sha1_to_hex (&buf[1], sha);
     369  memcpy (&buf[1+2*SHA_DIGEST_LENGTH], &salt, saltval_len);
     370  buf[1+2*SHA_DIGEST_LENGTH + saltval_len] = '\0';
     371  buf[0] = '{'; /* signal that this is a hash. this makes saving/restoring easier */
     372
     373  return tr_strdup (&buf);
    370374}
    371375
     
    373377tr_ssha1_matches (const char * source, const char * pass)
    374378{
    375     char * salt;
    376     size_t saltlen;
    377     char * hashed;
    378     uint8_t buf[SHA_DIGEST_LENGTH];
    379     bool result;
    380     const size_t sourcelen = strlen (source);
    381 
    382     /* extract the salt */
    383     if (sourcelen < 2*SHA_DIGEST_LENGTH-1)
    384         return false;
    385     saltlen = sourcelen - 2*SHA_DIGEST_LENGTH-1;
    386     salt = tr_malloc (saltlen);
    387     memcpy (salt, source + 2*SHA_DIGEST_LENGTH+1, saltlen);
    388 
    389     /* hash pass + salt */
    390     hashed = tr_malloc (2*SHA_DIGEST_LENGTH + saltlen + 2);
    391     tr_sha1 (buf, pass, strlen (pass), salt, saltlen, NULL);
    392     tr_sha1_to_hex (&hashed[1], buf);
    393     memcpy (hashed + 1+2*SHA_DIGEST_LENGTH, salt, saltlen);
    394     hashed[1+2*SHA_DIGEST_LENGTH + saltlen] = '\0';
    395     hashed[0] = '{';
    396 
    397     result = strcmp (source, hashed) == 0 ? true : false;
    398 
    399     tr_free (hashed);
    400     tr_free (salt);
    401 
    402     return result;
    403 }
     379  char * salt;
     380  size_t saltlen;
     381  char * hashed;
     382  uint8_t buf[SHA_DIGEST_LENGTH];
     383  bool result;
     384  const size_t sourcelen = strlen (source);
     385
     386  /* extract the salt */
     387  if (sourcelen < 2*SHA_DIGEST_LENGTH-1)
     388    return false;
     389  saltlen = sourcelen - 2*SHA_DIGEST_LENGTH-1;
     390  salt = tr_malloc (saltlen);
     391  memcpy (salt, source + 2*SHA_DIGEST_LENGTH+1, saltlen);
     392
     393  /* hash pass + salt */
     394  hashed = tr_malloc (2*SHA_DIGEST_LENGTH + saltlen + 2);
     395  tr_sha1 (buf, pass, strlen (pass), salt, saltlen, NULL);
     396  tr_sha1_to_hex (&hashed[1], buf);
     397  memcpy (hashed + 1+2*SHA_DIGEST_LENGTH, salt, saltlen);
     398  hashed[1+2*SHA_DIGEST_LENGTH + saltlen] = '\0';
     399  hashed[0] = '{';
     400
     401  result = strcmp (source, hashed) == 0 ? true : false;
     402
     403  tr_free (hashed);
     404  tr_free (salt);
     405
     406  return result;
     407}
  • trunk/libtransmission/peer-mgr.c

    r13801 r13863  
    4444enum
    4545{
    46     /* how frequently to cull old atoms */
    47     ATOM_PERIOD_MSEC = (60 * 1000),
    48 
    49     /* how frequently to change which peers are choked */
    50     RECHOKE_PERIOD_MSEC = (10 * 1000),
    51 
    52     /* an optimistically unchoked peer is immune from rechoking
    53        for this many calls to rechokeUploads (). */
    54     OPTIMISTIC_UNCHOKE_MULTIPLIER = 4,
    55 
    56     /* how frequently to reallocate bandwidth */
    57     BANDWIDTH_PERIOD_MSEC = 500,
    58 
    59     /* how frequently to age out old piece request lists */
    60     REFILL_UPKEEP_PERIOD_MSEC = (10 * 1000),
    61 
    62     /* how frequently to decide which peers live and die */
    63     RECONNECT_PERIOD_MSEC = 500,
    64 
    65     /* when many peers are available, keep idle ones this long */
    66     MIN_UPLOAD_IDLE_SECS = (60),
    67 
    68     /* when few peers are available, keep idle ones this long */
    69     MAX_UPLOAD_IDLE_SECS = (60 * 5),
    70 
    71     /* max number of peers to ask for per second overall.
    72      * this throttle is to avoid overloading the router */
    73     MAX_CONNECTIONS_PER_SECOND = 12,
    74 
    75     MAX_CONNECTIONS_PER_PULSE = (int)(MAX_CONNECTIONS_PER_SECOND * (RECONNECT_PERIOD_MSEC/1000.0)),
    76 
    77     /* number of bad pieces a peer is allowed to send before we ban them */
    78     MAX_BAD_PIECES_PER_PEER = 5,
    79 
    80     /* amount of time to keep a list of request pieces lying around
    81        before it's considered too old and needs to be rebuilt */
    82     PIECE_LIST_SHELF_LIFE_SECS = 60,
    83 
    84     /* use for bitwise operations w/peer_atom.flags2 */
    85     MYFLAG_BANNED = 1,
    86 
    87     /* use for bitwise operations w/peer_atom.flags2 */
    88     /* unreachable for now... but not banned.
    89      * if they try to connect to us it's okay */
    90     MYFLAG_UNREACHABLE = 2,
    91 
    92     /* the minimum we'll wait before attempting to reconnect to a peer */
    93     MINIMUM_RECONNECT_INTERVAL_SECS = 5,
    94 
    95     /** how long we'll let requests we've made linger before we cancel them */
    96     REQUEST_TTL_SECS = 90,
    97 
    98     NO_BLOCKS_CANCEL_HISTORY = 120,
    99 
    100     CANCEL_HISTORY_SEC = 60
     46  /* how frequently to cull old atoms */
     47  ATOM_PERIOD_MSEC = (60 * 1000),
     48
     49  /* how frequently to change which peers are choked */
     50  RECHOKE_PERIOD_MSEC = (10 * 1000),
     51
     52  /* an optimistically unchoked peer is immune from rechoking
     53     for this many calls to rechokeUploads (). */
     54  OPTIMISTIC_UNCHOKE_MULTIPLIER = 4,
     55
     56  /* how frequently to reallocate bandwidth */
     57  BANDWIDTH_PERIOD_MSEC = 500,
     58
     59  /* how frequently to age out old piece request lists */
     60  REFILL_UPKEEP_PERIOD_MSEC = (10 * 1000),
     61
     62  /* how frequently to decide which peers live and die */
     63  RECONNECT_PERIOD_MSEC = 500,
     64
     65  /* when many peers are available, keep idle ones this long */
     66  MIN_UPLOAD_IDLE_SECS = (60),
     67
     68  /* when few peers are available, keep idle ones this long */
     69  MAX_UPLOAD_IDLE_SECS = (60 * 5),
     70
     71  /* max number of peers to ask for per second overall.
     72   * this throttle is to avoid overloading the router */
     73  MAX_CONNECTIONS_PER_SECOND = 12,
     74
     75  MAX_CONNECTIONS_PER_PULSE = (int)(MAX_CONNECTIONS_PER_SECOND * (RECONNECT_PERIOD_MSEC/1000.0)),
     76
     77  /* number of bad pieces a peer is allowed to send before we ban them */
     78  MAX_BAD_PIECES_PER_PEER = 5,
     79
     80  /* amount of time to keep a list of request pieces lying around
     81     before it's considered too old and needs to be rebuilt */
     82  PIECE_LIST_SHELF_LIFE_SECS = 60,
     83
     84  /* use for bitwise operations w/peer_atom.flags2 */
     85  MYFLAG_BANNED = 1,
     86
     87  /* use for bitwise operations w/peer_atom.flags2 */
     88  /* unreachable for now... but not banned.
     89   * if they try to connect to us it's okay */
     90  MYFLAG_UNREACHABLE = 2,
     91
     92  /* the minimum we'll wait before attempting to reconnect to a peer */
     93  MINIMUM_RECONNECT_INTERVAL_SECS = 5,
     94
     95  /** how long we'll let requests we've made linger before we cancel them */
     96  REQUEST_TTL_SECS = 90,
     97
     98  NO_BLOCKS_CANCEL_HISTORY = 120,
     99
     100  CANCEL_HISTORY_SEC = 60
    101101};
    102102
     
    118118struct peer_atom
    119119{
    120     uint8_t     fromFirst;          /* where the peer was first found */
    121     uint8_t     fromBest;           /* the "best" value of where the peer has been found */
    122     uint8_t     flags;              /* these match the added_f flags */
    123     uint8_t     flags2;             /* flags that aren't defined in added_f */
    124     int8_t      seedProbability;    /* how likely is this to be a seed... [0..100] or -1 for unknown */
    125     int8_t      blocklisted;        /* -1 for unknown, true for blocklisted, false for not blocklisted */
    126 
    127     tr_port     port;
    128     bool        utp_failed;         /* We recently failed to connect over uTP */
    129     uint16_t    numFails;
    130     time_t      time;               /* when the peer's connection status last changed */
    131     time_t      piece_data_time;
    132 
    133     time_t      lastConnectionAttemptAt;
    134     time_t      lastConnectionAt;
    135 
    136     /* similar to a TTL field, but less rigid --
    137      * if the swarm is small, the atom will be kept past this date. */
    138     time_t      shelf_date;
    139     tr_peer   * peer;               /* will be NULL if not connected */
    140     tr_address  addr;
     120  uint8_t     fromFirst;          /* where the peer was first found */
     121  uint8_t     fromBest;           /* the "best" value of where the peer has been found */
     122  uint8_t     flags;              /* these match the added_f flags */
     123  uint8_t     flags2;             /* flags that aren't defined in added_f */
     124  int8_t      seedProbability;    /* how likely is this to be a seed... [0..100] or -1 for unknown */
     125  int8_t      blocklisted;        /* -1 for unknown, true for blocklisted, false for not blocklisted */
     126
     127  tr_port     port;
     128  bool        utp_failed;         /* We recently failed to connect over uTP */
     129  uint16_t    numFails;
     130  time_t      time;               /* when the peer's connection status last changed */
     131  time_t      piece_data_time;
     132
     133  time_t      lastConnectionAttemptAt;
     134  time_t      lastConnectionAt;
     135
     136  /* similar to a TTL field, but less rigid --
     137   * if the swarm is small, the atom will be kept past this date. */
     138  time_t      shelf_date;
     139  tr_peer   * peer;               /* will be NULL if not connected */
     140  tr_address  addr;
    141141};
    142142
     
    147147tr_isAtom (const struct peer_atom * atom)
    148148{
    149     return (atom != NULL)
    150         && (atom->fromFirst < TR_PEER_FROM__MAX)
    151         && (atom->fromBest < TR_PEER_FROM__MAX)
    152         && (tr_address_is_valid (&atom->addr));
     149  return (atom != NULL)
     150      && (atom->fromFirst < TR_PEER_FROM__MAX)
     151      && (atom->fromBest < TR_PEER_FROM__MAX)
     152      && (tr_address_is_valid (&atom->addr));
    153153}
    154154#endif
     
    157157tr_atomAddrStr (const struct peer_atom * atom)
    158158{
    159     return atom ? tr_peerIoAddrStr (&atom->addr, atom->port) : "[no atom]";
     159  return atom ? tr_peerIoAddrStr (&atom->addr, atom->port) : "[no atom]";
    160160}
    161161
    162162struct block_request
    163163{
    164     tr_block_index_t block;
    165     tr_peer * peer;
    166     time_t sentAt;
     164  tr_block_index_t block;
     165  tr_peer * peer;
     166  time_t sentAt;
    167167};
    168168
    169169struct weighted_piece
    170170{
    171     tr_piece_index_t index;
    172     int16_t salt;
    173     int16_t requestCount;
     171  tr_piece_index_t index;
     172  int16_t salt;
     173  int16_t requestCount;
    174174};
    175175
    176176enum piece_sort_state
    177177{
    178     PIECES_UNSORTED,
    179     PIECES_SORTED_BY_INDEX,
    180     PIECES_SORTED_BY_WEIGHT
     178  PIECES_UNSORTED,
     179  PIECES_SORTED_BY_INDEX,
     180  PIECES_SORTED_BY_WEIGHT
    181181};
    182182
     
    184184typedef struct tr_torrent_peers
    185185{
    186     tr_ptrArray                outgoingHandshakes; /* tr_handshake */
    187     tr_ptrArray                pool; /* struct peer_atom */
    188     tr_ptrArray                peers; /* tr_peer */
    189     tr_ptrArray                webseeds; /* tr_webseed */
    190 
    191     tr_torrent               * tor;
    192     struct tr_peerMgr        * manager;
    193 
    194     tr_peer                  * optimistic; /* the optimistic peer, or NULL if none */
    195     int                        optimisticUnchokeTimeScaler;
    196 
    197     bool                       isRunning;
    198     bool                       needsCompletenessCheck;
    199 
    200     struct block_request     * requests;
    201     int                        requestCount;
    202     int                        requestAlloc;
    203 
    204     struct weighted_piece    * pieces;
    205     int                        pieceCount;
    206     enum piece_sort_state      pieceSortState;
    207 
    208     /* An array of pieceCount items stating how many peers have each piece.
    209        This is used to help us for downloading pieces "rarest first."
    210        This may be NULL if we don't have metainfo yet, or if we're not
    211        downloading and don't care about rarity */
    212     uint16_t                 * pieceReplication;
    213     size_t                     pieceReplicationSize;
    214 
    215     int                        interestedCount;
    216     int                        maxPeers;
    217     time_t                     lastCancel;
    218 
    219     /* Before the endgame this should be 0. In endgame, is contains the average
    220      * number of pending requests per peer. Only peers which have more pending
    221      * requests are considered 'fast' are allowed to request a block that's
    222      * already been requested from another (slower?) peer. */
    223     int                        endgame;
     186  tr_ptrArray                outgoingHandshakes; /* tr_handshake */
     187  tr_ptrArray                pool; /* struct peer_atom */
     188  tr_ptrArray                peers; /* tr_peer */
     189  tr_ptrArray                webseeds; /* tr_webseed */
     190
     191  tr_torrent               * tor;
     192  struct tr_peerMgr        * manager;
     193
     194  tr_peer                  * optimistic; /* the optimistic peer, or NULL if none */
     195  int                        optimisticUnchokeTimeScaler;
     196
     197  bool                       isRunning;
     198  bool                       needsCompletenessCheck;
     199
     200  struct block_request     * requests;
     201  int                        requestCount;
     202  int                        requestAlloc;
     203
     204  struct weighted_piece    * pieces;
     205  int                        pieceCount;
     206  enum piece_sort_state      pieceSortState;
     207
     208  /* An array of pieceCount items stating how many peers have each piece.
     209     This is used to help us for downloading pieces "rarest first."
     210     This may be NULL if we don't have metainfo yet, or if we're not
     211     downloading and don't care about rarity */
     212  uint16_t                 * pieceReplication;
     213  size_t                     pieceReplicationSize;
     214
     215  int                        interestedCount;
     216  int                        maxPeers;
     217  time_t                     lastCancel;
     218
     219  /* Before the endgame this should be 0. In endgame, is contains the average
     220   * number of pending requests per peer. Only peers which have more pending
     221   * requests are considered 'fast' are allowed to request a block that's
     222   * already been requested from another (slower?) peer. */
     223  int                        endgame;
    224224}
    225225Torrent;
     
    227227struct tr_peerMgr
    228228{
    229     tr_session    * session;
    230     tr_ptrArray     incomingHandshakes; /* tr_handshake */
    231     struct event  * bandwidthTimer;
    232     struct event  * rechokeTimer;
    233     struct event  * refillUpkeepTimer;
    234     struct event  * atomTimer;
     229  tr_session    * session;
     230  tr_ptrArray     incomingHandshakes; /* tr_handshake */
     231  struct event  * bandwidthTimer;
     232  struct event  * rechokeTimer;
     233  struct event  * refillUpkeepTimer;
     234  struct event  * atomTimer;
    235235};
    236236
     
    258258managerLock (const struct tr_peerMgr * manager)
    259259{
    260     tr_sessionLock (manager->session);
     260  tr_sessionLock (manager->session);
    261261}
    262262
     
    264264managerUnlock (const struct tr_peerMgr * manager)
    265265{
    266     tr_sessionUnlock (manager->session);
     266  tr_sessionUnlock (manager->session);
    267267}
    268268
     
    270270torrentLock (Torrent * torrent)
    271271{
    272     managerLock (torrent->manager);
     272  managerLock (torrent->manager);
    273273}
    274274
     
    276276torrentUnlock (Torrent * torrent)
    277277{
    278     managerUnlock (torrent->manager);
     278  managerUnlock (torrent->manager);
    279279}
    280280
     
    282282torrentIsLocked (const Torrent * t)
    283283{
    284     return tr_sessionIsLocked (t->manager->session);
     284  return tr_sessionIsLocked (t->manager->session);
    285285}
    286286
     
    292292handshakeCompareToAddr (const void * va, const void * vb)
    293293{
    294     const tr_handshake * a = va;
    295 
    296     return tr_address_compare (tr_handshakeGetAddr (a, NULL), vb);
     294  const tr_handshake * a = va;
     295
     296  return tr_address_compare (tr_handshakeGetAddr (a, NULL), vb);
    297297}
    298298
     
    300300handshakeCompare (const void * a, const void * b)
    301301{
    302     return handshakeCompareToAddr (a, tr_handshakeGetAddr (b, NULL));
     302  return handshakeCompareToAddr (a, tr_handshakeGetAddr (b, NULL));
    303303}
    304304
     
    306306getExistingHandshake (tr_ptrArray * handshakes, const tr_address * addr)
    307307{
    308     if (tr_ptrArrayEmpty (handshakes))
    309         return NULL;
    310 
    311     return tr_ptrArrayFindSorted (handshakes, addr, handshakeCompareToAddr);
     308  if (tr_ptrArrayEmpty (handshakes))
     309    return NULL;
     310
     311  return tr_ptrArrayFindSorted (handshakes, addr, handshakeCompareToAddr);
    312312}
    313313
     
    315315comparePeerAtomToAddress (const void * va, const void * vb)
    316316{
    317     const struct peer_atom * a = va;
    318 
    319     return tr_address_compare (&a->addr, vb);
     317  const struct peer_atom * a = va;
     318
     319  return tr_address_compare (&a->addr, vb);
    320320}
    321321
     
    323323compareAtomsByAddress (const void * va, const void * vb)
    324324{
    325     const struct peer_atom * b = vb;
    326 
    327     assert (tr_isAtom (b));
    328 
    329     return comparePeerAtomToAddress (va, &b->addr);
     325  const struct peer_atom * b = vb;
     326
     327  assert (tr_isAtom (b));
     328
     329  return comparePeerAtomToAddress (va, &b->addr);
    330330}
    331331
     
    337337tr_peerAddress (const tr_peer * peer)
    338338{
    339     return &peer->atom->addr;
     339  return &peer->atom->addr;
    340340}
    341341
     
    344344                    const uint8_t * hash)
    345345{
    346     tr_torrent * tor = tr_torrentFindFromHash (manager->session, hash);
    347 
    348     return tor == NULL ? NULL : tor->torrentPeers;
     346  tr_torrent * tor = tr_torrentFindFromHash (manager->session, hash);
     347
     348  return tor == NULL ? NULL : tor->torrentPeers;
    349349}
    350350
     
    352352peerCompare (const void * a, const void * b)
    353353{
    354     return tr_address_compare (tr_peerAddress (a), tr_peerAddress (b));
     354  return tr_address_compare (tr_peerAddress (a), tr_peerAddress (b));
    355355}
    356356
     
    359359                 const tr_address * addr)
    360360{
    361     Torrent * tt = (Torrent*)t;
    362     return tr_ptrArrayFindSorted (&tt->pool, addr, comparePeerAtomToAddress);
     361  Torrent * tt = (Torrent*)t;
     362  return tr_ptrArrayFindSorted (&tt->pool, addr, comparePeerAtomToAddress);
    363363}
    364364
     
    366366peerIsInUse (const Torrent * ct, const struct peer_atom * atom)
    367367{
    368     Torrent * t = (Torrent*) ct;
    369 
    370     assert (torrentIsLocked (t));
    371 
    372     return (atom->peer != NULL)
    373         || getExistingHandshake (&t->outgoingHandshakes, &atom->addr)
    374         || getExistingHandshake (&t->manager->incomingHandshakes, &atom->addr);
     368  Torrent * t = (Torrent*) ct;
     369
     370  assert (torrentIsLocked (t));
     371
     372  return (atom->peer != NULL)
     373      || getExistingHandshake (&t->outgoingHandshakes, &atom->addr)
     374      || getExistingHandshake (&t->manager->incomingHandshakes, &atom->addr);
    375375}
    376376
     
    378378tr_peerConstruct (tr_peer * peer)
    379379{
    380     memset (peer, 0, sizeof (tr_peer));
    381 
    382     peer->have = TR_BITFIELD_INIT;
     380  memset (peer, 0, sizeof (tr_peer));
     381
     382  peer->have = TR_BITFIELD_INIT;
    383383}
    384384
     
    386386peerNew (struct peer_atom * atom)
    387387{
    388     tr_peer * peer = tr_new (tr_peer, 1);
    389     tr_peerConstruct (peer);
    390 
    391     peer->atom = atom;
    392     atom->peer = peer;
    393 
    394     return peer;
     388  tr_peer * peer = tr_new (tr_peer, 1);
     389  tr_peerConstruct (peer);
     390
     391  peer->atom = atom;
     392  atom->peer = peer;
     393
     394  return peer;
    395395}
    396396
     
    398398getPeer (Torrent * torrent, struct peer_atom * atom)
    399399{
    400     tr_peer * peer;
    401 
    402     assert (torrentIsLocked (torrent));
    403 
    404     peer = atom->peer;
    405 
    406     if (peer == NULL)
    407     {
    408         peer = peerNew (atom);
    409         tr_bitfieldConstruct (&peer->have, torrent->tor->info.pieceCount);
    410         tr_bitfieldConstruct (&peer->blame, torrent->tor->blockCount);
    411         tr_ptrArrayInsertSorted (&torrent->peers, peer, peerCompare);
    412     }
    413 
    414     return peer;
     400  tr_peer * peer;
     401
     402  assert (torrentIsLocked (torrent));
     403
     404  peer = atom->peer;
     405
     406  if (peer == NULL)
     407    {
     408      peer = peerNew (atom);
     409      tr_bitfieldConstruct (&peer->have, torrent->tor->info.pieceCount);
     410      tr_bitfieldConstruct (&peer->blame, torrent->tor->blockCount);
     411      tr_ptrArrayInsertSorted (&torrent->peers, peer, peerCompare);
     412    }
     413
     414  return peer;
    415415}
    416416
     
    420420tr_peerDestruct (tr_torrent * tor, tr_peer * peer)
    421421{
    422     assert (peer != NULL);
    423 
    424     peerDeclinedAllRequests (tor->torrentPeers, peer);
    425 
    426     if (peer->msgs != NULL)
    427         tr_peerMsgsFree (peer->msgs);
    428 
    429     if (peer->io) {
    430         tr_peerIoClear (peer->io);
    431         tr_peerIoUnref (peer->io); /* balanced by the ref in handshakeDoneCB () */
    432     }
    433 
    434     tr_bitfieldDestruct (&peer->have);
    435     tr_bitfieldDestruct (&peer->blame);
    436 
    437     if (peer->atom)
    438         peer->atom->peer = NULL;
     422  assert (peer != NULL);
     423
     424  peerDeclinedAllRequests (tor->torrentPeers, peer);
     425
     426  if (peer->msgs != NULL)
     427    tr_peerMsgsFree (peer->msgs);
     428
     429  if (peer->io)
     430    {
     431      tr_peerIoClear (peer->io);
     432      tr_peerIoUnref (peer->io); /* balanced by the ref in handshakeDoneCB () */
     433    }
     434
     435  tr_bitfieldDestruct (&peer->have);
     436  tr_bitfieldDestruct (&peer->blame);
     437
     438  if (peer->atom)
     439    peer->atom->peer = NULL;
    439440}
    440441
     
    442443peerDelete (Torrent * t, tr_peer * peer)
    443444{
    444     tr_peerDestruct (t->tor, peer);
    445     tr_free (peer);
     445  tr_peerDestruct (t->tor, peer);
     446  tr_free (peer);
    446447}
    447448
     
    449450replicationExists (const Torrent * t)
    450451{
    451     return t->pieceReplication != NULL;
     452  return t->pieceReplication != NULL;
    452453}
    453454
     
    455456replicationFree (Torrent * t)
    456457{
    457     tr_free (t->pieceReplication);
    458     t->pieceReplication = NULL;
    459     t->pieceReplicationSize = 0;
     458  tr_free (t->pieceReplication);
     459  t->pieceReplication = NULL;
     460  t->pieceReplicationSize = 0;
    460461}
    461462
     
    463464replicationNew (Torrent * t)
    464465{
    465     tr_piece_index_t piece_i;
    466     const tr_piece_index_t piece_count = t->tor->info.pieceCount;
    467     tr_peer ** peers = (tr_peer**) tr_ptrArrayBase (&t->peers);
    468     const int peer_count = tr_ptrArraySize (&t->peers);
    469 
    470     assert (!replicationExists (t));
    471 
    472     t->pieceReplicationSize = piece_count;
    473     t->pieceReplication = tr_new0 (uint16_t, piece_count);
    474 
    475     for (piece_i=0; piece_i<piece_count; ++piece_i)
    476     {
    477         int peer_i;
    478         uint16_t r = 0;
    479 
    480         for (peer_i=0; peer_i<peer_count; ++peer_i)
    481             if (tr_bitfieldHas (&peers[peer_i]->have, piece_i))
    482                 ++r;
    483 
    484         t->pieceReplication[piece_i] = r;
     466  tr_piece_index_t piece_i;
     467  const tr_piece_index_t piece_count = t->tor->info.pieceCount;
     468  tr_peer ** peers = (tr_peer**) tr_ptrArrayBase (&t->peers);
     469  const int peer_count = tr_ptrArraySize (&t->peers);
     470
     471  assert (!replicationExists (t));
     472
     473  t->pieceReplicationSize = piece_count;
     474  t->pieceReplication = tr_new0 (uint16_t, piece_count);
     475
     476  for (piece_i=0; piece_i<piece_count; ++piece_i)
     477    {
     478      int peer_i;
     479      uint16_t r = 0;
     480
     481      for (peer_i=0; peer_i<peer_count; ++peer_i)
     482        if (tr_bitfieldHas (&peers[peer_i]->have, piece_i))
     483          ++r;
     484
     485      t->pieceReplication[piece_i] = r;
    485486    }
    486487}
     
    489490torrentFree (void * vt)
    490491{
    491     Torrent * t = vt;
    492 
    493     assert (t);
    494     assert (!t->isRunning);
    495     assert (torrentIsLocked (t));
    496     assert (tr_ptrArrayEmpty (&t->outgoingHandshakes));
    497     assert (tr_ptrArrayEmpty (&t->peers));
    498 
    499     tr_ptrArrayDestruct (&t->webseeds, (PtrArrayForeachFunc)tr_webseedFree);
    500     tr_ptrArrayDestruct (&t->pool, (PtrArrayForeachFunc)tr_free);
    501     tr_ptrArrayDestruct (&t->outgoingHandshakes, NULL);
    502     tr_ptrArrayDestruct (&t->peers, NULL);
    503 
    504     replicationFree (t);
    505 
    506     tr_free (t->requests);
    507     tr_free (t->pieces);
    508     tr_free (t);
     492  Torrent * t = vt;
     493
     494  assert (t);
     495  assert (!t->isRunning);
     496  assert (torrentIsLocked (t));
     497  assert (tr_ptrArrayEmpty (&t->outgoingHandshakes));
     498  assert (tr_ptrArrayEmpty (&t->peers));
     499
     500  tr_ptrArrayDestruct (&t->webseeds, (PtrArrayForeachFunc)tr_webseedFree);
     501  tr_ptrArrayDestruct (&t->pool, (PtrArrayForeachFunc)tr_free);
     502  tr_ptrArrayDestruct (&t->outgoingHandshakes, NULL);
     503  tr_ptrArrayDestruct (&t->peers, NULL);
     504
     505  replicationFree (t);
     506
     507  tr_free (t->requests);
     508  tr_free (t->pieces);
     509  tr_free (t);
    509510}
    510511
     
    514515rebuildWebseedArray (Torrent * t, tr_torrent * tor)
    515516{
    516     unsigned int i;
    517     const tr_info * inf = &tor->info;
    518 
    519     /* clear the array */
    520     tr_ptrArrayDestruct (&t->webseeds, (PtrArrayForeachFunc)tr_webseedFree);
    521     t->webseeds = TR_PTR_ARRAY_INIT;
    522 
    523     /* repopulate it */
    524     for (i = 0; i < inf->webseedCount; ++i)
    525     {
    526         tr_webseed * w = tr_webseedNew (tor, inf->webseeds[i], peerCallbackFunc, t);
    527         tr_ptrArrayAppend (&t->webseeds, w);
     517  unsigned int i;
     518  const tr_info * inf = &tor->info;
     519
     520  /* clear the array */
     521  tr_ptrArrayDestruct (&t->webseeds, (PtrArrayForeachFunc)tr_webseedFree);
     522  t->webseeds = TR_PTR_ARRAY_INIT;
     523
     524  /* repopulate it */
     525  for (i = 0; i < inf->webseedCount; ++i)
     526    {
     527      tr_webseed * w = tr_webseedNew (tor, inf->webseeds[i], peerCallbackFunc, t);
     528      tr_ptrArrayAppend (&t->webseeds, w);
    528529    }
    529530}
     
    532533torrentNew (tr_peerMgr * manager, tr_torrent * tor)
    533534{
    534     Torrent * t;
    535 
    536     t = tr_new0 (Torrent, 1);
    537     t->manager = manager;
    538     t->tor = tor;
    539     t->pool = TR_PTR_ARRAY_INIT;
    540     t->peers = TR_PTR_ARRAY_INIT;
    541     t->webseeds = TR_PTR_ARRAY_INIT;
    542     t->outgoingHandshakes = TR_PTR_ARRAY_INIT;
    543 
    544     rebuildWebseedArray (t, tor);
    545 
    546     return t;
     535  Torrent * t;
     536
     537  t = tr_new0 (Torrent, 1);
     538  t->manager = manager;
     539  t->tor = tor;
     540  t->pool = TR_PTR_ARRAY_INIT;
     541  t->peers = TR_PTR_ARRAY_INIT;
     542  t->webseeds = TR_PTR_ARRAY_INIT;
     543  t->outgoingHandshakes = TR_PTR_ARRAY_INIT;
     544
     545  rebuildWebseedArray (t, tor);
     546
     547  return t;
    547548}
    548549
     
    552553tr_peerMgrNew (tr_session * session)
    553554{
    554     tr_peerMgr * m = tr_new0 (tr_peerMgr, 1);
    555     m->session = session;
    556     m->incomingHandshakes = TR_PTR_ARRAY_INIT;
    557     ensureMgrTimersExist (m);
    558     return m;
     555  tr_peerMgr * m = tr_new0 (tr_peerMgr, 1);
     556  m->session = session;
     557  m->incomingHandshakes = TR_PTR_ARRAY_INIT;
     558  ensureMgrTimersExist (m);
     559  return m;
    559560}
    560561
     
    562563deleteTimer (struct event ** t)
    563564{
    564     if (*t != NULL)
    565     {
    566         event_free (*t);
    567         *t = NULL;
     565  if (*t != NULL)
     566    {
     567      event_free (*t);
     568      *t = NULL;
    568569    }
    569570}
     
    572573deleteTimers (struct tr_peerMgr * m)
    573574{
    574     deleteTimer (&m->atomTimer);
    575     deleteTimer (&m->bandwidthTimer);
    576     deleteTimer (&m->rechokeTimer);
    577     deleteTimer (&m->refillUpkeepTimer);
     575  deleteTimer (&m->atomTimer);
     576  deleteTimer (&m->bandwidthTimer);
     577  deleteTimer (&m->rechokeTimer);
     578  deleteTimer (&m->refillUpkeepTimer);
    578579}
    579580
     
    581582tr_peerMgrFree (tr_peerMgr * manager)
    582583{
    583     managerLock (manager);
    584 
    585     deleteTimers (manager);
    586 
    587     /* free the handshakes. Abort invokes handshakeDoneCB (), which removes
    588      * the item from manager->handshakes, so this is a little roundabout... */
    589     while (!tr_ptrArrayEmpty (&manager->incomingHandshakes))
    590         tr_handshakeAbort (tr_ptrArrayNth (&manager->incomingHandshakes, 0));
    591 
    592     tr_ptrArrayDestruct (&manager->incomingHandshakes, NULL);
    593 
    594     managerUnlock (manager);
    595     tr_free (manager);
     584  managerLock (manager);
     585
     586  deleteTimers (manager);
     587
     588  /* free the handshakes. Abort invokes handshakeDoneCB (), which removes
     589   * the item from manager->handshakes, so this is a little roundabout... */
     590  while (!tr_ptrArrayEmpty (&manager->incomingHandshakes))
     591    tr_handshakeAbort (tr_ptrArrayNth (&manager->incomingHandshakes, 0));
     592
     593  tr_ptrArrayDestruct (&manager->incomingHandshakes, NULL);
     594
     595  managerUnlock (manager);
     596  tr_free (manager);
    596597}
    597598
     
    599600clientIsDownloadingFrom (const tr_torrent * tor, const tr_peer * peer)
    600601{
    601     if (!tr_torrentHasMetadata (tor))
    602         return true;
    603 
    604     return peer->clientIsInterested && !peer->clientIsChoked;
     602  if (!tr_torrentHasMetadata (tor))
     603    return true;
     604
     605  return peer->clientIsInterested && !peer->clientIsChoked;
    605606}
    606607
     
    608609clientIsUploadingTo (const tr_peer * peer)
    609610{
    610     return peer->peerIsInterested && !peer->peerIsChoked;
     611  return peer->peerIsInterested && !peer->peerIsChoked;
    611612}
    612613
     
    618619tr_peerMgrOnBlocklistChanged (tr_peerMgr * mgr)
    619620{
    620     tr_torrent * tor = NULL;
    621     tr_session * session = mgr->session;
    622 
    623     /* we cache whether or not a peer is blocklisted...
    624        since the blocklist has changed, erase that cached value */
    625     while ((tor = tr_torrentNext (session, tor)))
    626     {
    627         int i;
    628         Torrent * t = tor->torrentPeers;
    629         const int n = tr_ptrArraySize (&t->pool);
    630         for (i=0; i<n; ++i) {
    631             struct peer_atom * atom = tr_ptrArrayNth (&t->pool, i);
    632             atom->blocklisted = -1;
     621  tr_torrent * tor = NULL;
     622  tr_session * session = mgr->session;
     623
     624  /* we cache whether or not a peer is blocklisted...
     625     since the blocklist has changed, erase that cached value */
     626  while ((tor = tr_torrentNext (session, tor)))
     627    {
     628      int i;
     629      Torrent * t = tor->torrentPeers;
     630      const int n = tr_ptrArraySize (&t->pool);
     631      for (i=0; i<n; ++i)
     632        {
     633          struct peer_atom * atom = tr_ptrArrayNth (&t->pool, i);
     634          atom->blocklisted = -1;
    633635        }
    634636    }
     
    638640isAtomBlocklisted (tr_session * session, struct peer_atom * atom)
    639641{
    640     if (atom->blocklisted < 0)
    641         atom->blocklisted = tr_sessionIsAddressBlocked (session, &atom->addr);
    642 
    643     assert (tr_isBool (atom->blocklisted));
    644     return atom->blocklisted;
     642  if (atom->blocklisted < 0)
     643    atom->blocklisted = tr_sessionIsAddressBlocked (session, &atom->addr);
     644
     645  assert (tr_isBool (atom->blocklisted));
     646  return atom->blocklisted;
    645647}
    646648
     
    653655atomSetSeedProbability (struct peer_atom * atom, int seedProbability)
    654656{
    655     assert (atom != NULL);
    656     assert (-1<=seedProbability && seedProbability<=100);
    657 
    658     atom->seedProbability = seedProbability;
    659 
    660     if (seedProbability == 100)
    661         atom->flags |= ADDED_F_SEED_FLAG;
    662     else if (seedProbability != -1)
    663         atom->flags &= ~ADDED_F_SEED_FLAG;
     657  assert (atom != NULL);
     658  assert (-1<=seedProbability && seedProbability<=100);
     659
     660  atom->seedProbability = seedProbability;
     661
     662  if (seedProbability == 100)
     663    atom->flags |= ADDED_F_SEED_FLAG;
     664  else if (seedProbability != -1)
     665    atom->flags &= ~ADDED_F_SEED_FLAG;
    664666}
    665667
     
    667669atomIsSeed (const struct peer_atom * atom)
    668670{
    669     return atom->seedProbability == 100;
     671  return atom->seedProbability == 100;
    670672}
    671673
     
    673675atomSetSeed (const Torrent * t, struct peer_atom * atom)
    674676{
    675     if (!atomIsSeed (atom))
    676     {
    677         tordbg (t, "marking peer %s as a seed", tr_atomAddrStr (atom));
    678 
    679         atomSetSeedProbability (atom, 100);
     677  if (!atomIsSeed (atom))
     678    {
     679      tordbg (t, "marking peer %s as a seed", tr_atomAddrStr (atom));
     680
     681      atomSetSeedProbability (atom, 100);
    680682    }
    681683}
     
    686688                      const tr_address  * addr)
    687689{
    688     bool isSeed = false;
    689     const Torrent * t = tor->torrentPeers;
    690     const struct peer_atom * atom = getExistingAtom (t, addr);
    691 
    692     if (atom)
    693         isSeed = atomIsSeed (atom);
    694 
    695     return isSeed;
     690  bool isSeed = false;
     691  const Torrent * t = tor->torrentPeers;
     692  const struct peer_atom * atom = getExistingAtom (t, addr);
     693
     694  if (atom)
     695    isSeed = atomIsSeed (atom);
     696
     697  return isSeed;
    696698}
    697699
     
    699701tr_peerMgrSetUtpSupported (tr_torrent * tor, const tr_address * addr)
    700702{
    701     struct peer_atom * atom = getExistingAtom (tor->torrentPeers, addr);
    702 
    703     if (atom)
    704         atom->flags |= ADDED_F_UTP_FLAGS;
     703  struct peer_atom * atom = getExistingAtom (tor->torrentPeers, addr);
     704
     705  if (atom)
     706    atom->flags |= ADDED_F_UTP_FLAGS;
    705707}
    706708
     
    708710tr_peerMgrSetUtpFailed (tr_torrent *tor, const tr_address *addr, bool failed)
    709711{
    710     struct peer_atom * atom = getExistingAtom (tor->torrentPeers, addr);
    711 
    712     if (atom)
    713         atom->utp_failed = failed;
     712  struct peer_atom * atom = getExistingAtom (tor->torrentPeers, addr);
     713
     714  if (atom)
     715    atom->utp_failed = failed;
    714716}
    715717
  • trunk/libtransmission/port-forwarding.c

    r13631 r13863  
    3333struct tr_shared
    3434{
    35     bool              isEnabled;
    36     bool              isShuttingDown;
    37     bool              doPortCheck;
    38 
    39     tr_port_forwarding    natpmpStatus;
    40     tr_port_forwarding    upnpStatus;
    41 
    42     tr_upnp            * upnp;
    43     tr_natpmp          * natpmp;
    44     tr_session          * session;
    45 
    46     struct event        * timer;
     35  bool isEnabled;
     36  bool isShuttingDown;
     37  bool doPortCheck;
     38
     39  tr_port_forwarding natpmpStatus;
     40  tr_port_forwarding upnpStatus;
     41
     42  tr_upnp * upnp;
     43  tr_natpmp * natpmp;
     44  tr_session * session;
     45
     46  struct event * timer;
    4747};
    4848
     
    5454getNatStateStr (int state)
    5555{
    56     switch (state)
    57     {
    58         case TR_PORT_MAPPING:   return _("Starting");
    59         case TR_PORT_MAPPED:    return _("Forwarded");
    60         case TR_PORT_UNMAPPING: return _("Stopping");
    61         case TR_PORT_UNMAPPED:  return _("Not forwarded");
    62         default:                return "???";
     56  switch (state)
     57    {
     58      case TR_PORT_MAPPING:   return _("Starting");
     59      case TR_PORT_MAPPED:    return _("Forwarded");
     60      case TR_PORT_UNMAPPING: return _("Stopping");
     61      case TR_PORT_UNMAPPED:  return _("Not forwarded");
     62      default:                return "???";
    6363    }
    6464}
     
    6767natPulse (tr_shared * s, bool do_check)
    6868{
    69     const tr_port private_peer_port = s->session->private_peer_port;
    70     const int is_enabled = s->isEnabled && !s->isShuttingDown;
    71     tr_port public_peer_port;
    72     int oldStatus;
    73     int newStatus;
    74 
    75     if (s->natpmp == NULL)
    76         s->natpmp = tr_natpmpInit ();
    77     if (s->upnp == NULL)
    78         s->upnp = tr_upnpInit ();
    79 
    80     oldStatus = tr_sharedTraversalStatus (s);
    81 
    82     s->natpmpStatus = tr_natpmpPulse (s->natpmp, private_peer_port, is_enabled, &public_peer_port);
    83     if (s->natpmpStatus == TR_PORT_MAPPED)
    84         s->session->public_peer_port = public_peer_port;
    85 
    86     s->upnpStatus = tr_upnpPulse (s->upnp, private_peer_port, is_enabled, do_check);
    87 
    88     newStatus = tr_sharedTraversalStatus (s);
    89 
    90     if (newStatus != oldStatus)
    91         tr_ninf (getKey (), _("State changed from \"%1$s\" to \"%2$s\""),
    92                 getNatStateStr (oldStatus),
    93                 getNatStateStr (newStatus));
     69  int oldStatus;
     70  int newStatus;
     71  tr_port public_peer_port;
     72  const tr_port private_peer_port = s->session->private_peer_port;
     73  const int is_enabled = s->isEnabled && !s->isShuttingDown;
     74
     75  if (s->natpmp == NULL)
     76    s->natpmp = tr_natpmpInit ();
     77
     78  if (s->upnp == NULL)
     79    s->upnp = tr_upnpInit ();
     80
     81  oldStatus = tr_sharedTraversalStatus (s);
     82
     83  s->natpmpStatus = tr_natpmpPulse (s->natpmp, private_peer_port, is_enabled, &public_peer_port);
     84  if (s->natpmpStatus == TR_PORT_MAPPED)
     85    s->session->public_peer_port = public_peer_port;
     86
     87  s->upnpStatus = tr_upnpPulse (s->upnp, private_peer_port, is_enabled, do_check);
     88
     89  newStatus = tr_sharedTraversalStatus (s);
     90
     91  if (newStatus != oldStatus)
     92    tr_ninf (getKey (), _("State changed from \"%1$s\" to \"%2$s\""),
     93             getNatStateStr (oldStatus),
     94             getNatStateStr (newStatus));
    9495}
    9596
     
    9798set_evtimer_from_status (tr_shared * s)
    9899{
    99     int sec=0, msec=0;
    100 
    101     /* when to wake up again */
    102     switch (tr_sharedTraversalStatus (s))
    103     {
    104         case TR_PORT_MAPPED:
    105             /* if we're mapped, everything is fine... check back in 20 minutes
    106              * to renew the port forwarding if it's expired */
    107             s->doPortCheck = true;
    108             sec = 60 * 20;
    109             break;
    110 
    111         case TR_PORT_ERROR:
    112             /* some kind of an error. wait 60 seconds and retry */
    113             sec = 60;
    114             break;
    115 
    116         default:
    117             /* in progress. pulse frequently. */
    118             msec = 333000;
    119             break;
    120     }
    121 
    122     if (s->timer != NULL)
    123         tr_timerAdd (s->timer, sec, msec);
     100  int sec=0, msec=0;
     101
     102  /* when to wake up again */
     103  switch (tr_sharedTraversalStatus (s))
     104    {
     105      case TR_PORT_MAPPED:
     106        /* if we're mapped, everything is fine... check back in 20 minutes
     107         * to renew the port forwarding if it's expired */
     108        s->doPortCheck = true;
     109        sec = 60 * 20;
     110        break;
     111
     112      case TR_PORT_ERROR:
     113        /* some kind of an error. wait 60 seconds and retry */
     114        sec = 60;
     115        break;
     116
     117      default:
     118        /* in progress. pulse frequently. */
     119        msec = 333000;
     120        break;
     121    }
     122
     123  if (s->timer != NULL)
     124    tr_timerAdd (s->timer, sec, msec);
    124125}
    125126
     
    127128onTimer (int fd UNUSED, short what UNUSED, void * vshared)
    128129{
    129     tr_shared * s = vshared;
    130 
    131     assert (s);
    132     assert (s->timer);
    133 
    134     /* do something */
    135     natPulse (s, s->doPortCheck);
    136     s->doPortCheck = false;
    137 
    138     /* set up the timer for the next pulse */
    139     set_evtimer_from_status (s);
     130  tr_shared * s = vshared;
     131
     132  assert (s);
     133  assert (s->timer);
     134
     135  /* do something */
     136  natPulse (s, s->doPortCheck);
     137  s->doPortCheck = false;
     138
     139  /* set up the timer for the next pulse */
     140  set_evtimer_from_status (s);
    140141}
    141142
     
    147148tr_sharedInit (tr_session  * session)
    148149{
    149     tr_shared * s = tr_new0 (tr_shared, 1);
    150 
    151     s->session      = session;
    152     s->isEnabled    = false;
    153     s->upnpStatus  = TR_PORT_UNMAPPED;
    154     s->natpmpStatus = TR_PORT_UNMAPPED;
     150  tr_shared * s = tr_new0 (tr_shared, 1);
     151
     152  s->session = session;
     153  s->isEnabled = false;
     154  s->upnpStatus = TR_PORT_UNMAPPED;
     155  s->natpmpStatus = TR_PORT_UNMAPPED;
    155156
    156157#if 0
    157     if (isEnabled)
    158     {
    159         s->timer = tr_new0 (struct event, 1);
    160         evtimer_set (s->timer, onTimer, s);
    161         tr_timerAdd (s->timer, 0, 333000);
     158  if (isEnabled)
     159    {
     160      s->timer = tr_new0 (struct event, 1);
     161      evtimer_set (s->timer, onTimer, s);
     162      tr_timerAdd (s->timer, 0, 333000);
    162163    }
    163164#endif
    164165
    165     return s;
     166  return s;
    166167}
    167168
     
    169170stop_timer (tr_shared * s)
    170171{
    171     if (s->timer != NULL)
    172     {
    173         event_free (s->timer);
    174         s->timer = NULL;
     172  if (s->timer != NULL)
     173    {
     174      event_free (s->timer);
     175      s->timer = NULL;
    175176    }
    176177}
     
    179180stop_forwarding (tr_shared * s)
    180181{
    181     tr_ninf (getKey (), "%s", _("Stopped"));
    182     natPulse (s, false);
    183 
    184     tr_natpmpClose (s->natpmp);
    185     s->natpmp = NULL;
    186     s->natpmpStatus = TR_PORT_UNMAPPED;
    187 
    188     tr_upnpClose (s->upnp);
    189     s->upnp = NULL;
    190     s->upnpStatus = TR_PORT_UNMAPPED;
    191 
    192     stop_timer (s);
     182  tr_ninf (getKey (), "%s", _("Stopped"));
     183  natPulse (s, false);
     184
     185  tr_natpmpClose (s->natpmp);
     186  s->natpmp = NULL;
     187  s->natpmpStatus = TR_PORT_UNMAPPED;
     188
     189  tr_upnpClose (s->upnp);
     190  s->upnp = NULL;
     191  s->upnpStatus = TR_PORT_UNMAPPED;
     192
     193  stop_timer (s);
    193194}
    194195
     
    196197tr_sharedClose (tr_session * session)
    197198{
    198     tr_shared * s = session->shared;
    199 
    200     s->isShuttingDown = true;
    201     stop_forwarding (s);
    202     s->session->shared = NULL;
    203     tr_free (s);
     199  tr_shared * s = session->shared;
     200
     201  s->isShuttingDown = true;
     202  stop_forwarding (s);
     203  s->session->shared = NULL;
     204  tr_free (s);
    204205}
    205206
     
    207208start_timer (tr_shared * s)
    208209{
    209     s->timer = evtimer_new (s->session->event_base, onTimer, s);
    210     set_evtimer_from_status (s);
     210  s->timer = evtimer_new (s->session->event_base, onTimer, s);
     211  set_evtimer_from_status (s);
    211212}
    212213
     
    214215tr_sharedTraversalEnable (tr_shared * s, bool isEnabled)
    215216{
    216     if ((s->isEnabled = isEnabled))
    217         start_timer (s);
    218     else
    219         stop_forwarding (s);
     217  if ((s->isEnabled = isEnabled))
     218    start_timer (s);
     219  else
     220    stop_forwarding (s);
    220221}
    221222
     
    223224tr_sharedPortChanged (tr_session * session)
    224225{
    225     tr_shared * s = session->shared;
    226 
    227     if (s->isEnabled)
    228     {
    229         stop_timer (s);
    230         natPulse (s, false);
    231         start_timer (s);
     226  tr_shared * s = session->shared;
     227
     228  if (s->isEnabled)
     229    {
     230      stop_timer (s);
     231      natPulse (s, false);
     232      start_timer (s);
    232233    }
    233234}
     
    236237tr_sharedTraversalIsEnabled (const tr_shared * s)
    237238{
    238     return s->isEnabled;
     239  return s->isEnabled;
    239240}
    240241
     
    242243tr_sharedTraversalStatus (const tr_shared * s)
    243244{
    244     return MAX (s->natpmpStatus, s->upnpStatus);
    245 }
     245  return MAX (s->natpmpStatus, s->upnpStatus);
     246}
  • trunk/libtransmission/utils.c

    r13852 r13863  
    7272
    7373#ifndef WIN32
    74     /* make null versions of these win32 functions */
    75     static inline int IsDebuggerPresent (void) { return false; }
    76     static inline void OutputDebugString (const void * unused UNUSED) { }
     74  /* make null versions of these win32 functions */
     75  static inline int IsDebuggerPresent (void) { return false; }
     76  static inline void OutputDebugString (const void * unused UNUSED) { }
    7777#endif
    7878
     
    8484getMessageLock (void)
    8585{
    86     static tr_lock * l = NULL;
    87 
    88     if (!l)
    89         l = tr_lockNew ();
    90 
    91     return l;
     86  static tr_lock * l = NULL;
     87
     88  if (!l)
     89    l = tr_lockNew ();
     90
     91  return l;
    9292}
    9393
     
    9595tr_getLog (void)
    9696{
    97     static bool initialized = false;
    98     static FILE * file = NULL;
    99 
    100     if (!initialized)
    101     {
    102         const char * str = getenv ("TR_DEBUG_FD");
    103         int          fd = 0;
    104         if (str && *str)
    105             fd = atoi (str);
    106         switch (fd)
     97  static bool initialized = false;
     98  static FILE * file = NULL;
     99
     100  if (!initialized)
     101    {
     102      int fd = 0;
     103      const char * str = getenv ("TR_DEBUG_FD");
     104
     105      if (str && *str)
     106        fd = atoi (str);
     107
     108      switch (fd)
    107109        {
    108             case 1:
    109                 file = stdout; break;
    110 
    111             case 2:
    112                 file = stderr; break;
    113 
    114             default:
    115                 file = NULL; break;
     110          case 1:
     111            file = stdout;
     112            break;
     113
     114          case 2:
     115            file = stderr;
     116            break;
     117
     118          default:
     119            file = NULL;
     120            break;
    116121        }
    117         initialized = true;
    118     }
    119 
    120     return file;
     122
     123      initialized = true;
     124    }
     125
     126  return file;
    121127}
    122128
     
    130136tr_setMessageQueuing (bool enabled)
    131137{
    132     messageQueuing = enabled;
     138  messageQueuing = enabled;
    133139}
    134140
     
    136142tr_getMessageQueuing (void)
    137143{
    138     return messageQueuing != 0;
     144  return messageQueuing != 0;
    139145}
    140146
     
    142148tr_getQueuedMessages (void)
    143149{
    144     tr_msg_list * ret;
    145     tr_lockLock (getMessageLock ());
    146 
    147     ret = messageQueue;
    148     messageQueue = NULL;
    149     messageQueueTail = &messageQueue;
    150 
    151     messageQueueCount = 0;
    152 
    153     tr_lockUnlock (getMessageLock ());
    154     return ret;
     150  tr_msg_list * ret;
     151  tr_lockLock (getMessageLock ());
     152
     153  ret = messageQueue;
     154  messageQueue = NULL;
     155  messageQueueTail = &messageQueue;
     156
     157  messageQueueCount = 0;
     158
     159  tr_lockUnlock (getMessageLock ());
     160  return ret;
    155161}
    156162
     
    158164tr_freeMessageList (tr_msg_list * list)
    159165{
    160     tr_msg_list * next;
    161 
    162     while (NULL != list)
    163     {
    164         next = list->next;
    165         free (list->message);
    166         free (list->name);
    167         free (list);
    168         list = next;
     166  tr_msg_list * next;
     167
     168  while (NULL != list)
     169    {
     170      next = list->next;
     171      free (list->message);
     172      free (list->name);
     173      free (list);
     174      list = next;
    169175    }
    170176}
     
    178184{
    179185#ifdef HAVE_LOCALTIME_R
    180     return localtime_r (_clock, _result);
     186  return localtime_r (_clock, _result);
    181187#else
    182     struct tm *p = localtime (_clock);
    183     if (p)
    184         * (_result) = *p;
    185     return p;
     188  struct tm *p = localtime (_clock);
     189  if (p)
     190    * (_result) = *p;
     191  return p;
    186192#endif
    187193}
     
    190196tr_getLogTimeStr (char * buf, int buflen)
    191197{
    192     char          tmp[64];
    193     struct tm      now_tm;
    194     struct timeval tv;
    195     time_t        seconds;
    196     int            milliseconds;
    197 
    198     gettimeofday (&tv, NULL);
    199 
    200     seconds = tv.tv_sec;
    201     tr_localtime_r (&seconds, &now_tm);
    202     strftime (tmp, sizeof (tmp), "%H:%M:%S", &now_tm);
    203     milliseconds = tv.tv_usec / 1000;
    204     tr_snprintf (buf, buflen, "%s.%03d", tmp, milliseconds);
    205 
    206     return buf;
     198  char tmp[64];
     199  struct tm now_tm;
     200  struct timeval tv;
     201  time_t seconds;
     202  int milliseconds;
     203
     204  gettimeofday (&tv, NULL);
     205
     206  seconds = tv.tv_sec;
     207  tr_localtime_r (&seconds, &now_tm);
     208  strftime (tmp, sizeof (tmp), "%H:%M:%S", &now_tm);
     209  milliseconds = tv.tv_usec / 1000;
     210  tr_snprintf (buf, buflen, "%s.%03d", tmp, milliseconds);
     211
     212  return buf;
    207213}
    208214
     
    210216tr_deepLoggingIsActive (void)
    211217{
    212     static int8_t deepLoggingIsActive = -1;
    213 
    214     if (deepLoggingIsActive < 0)
    215         deepLoggingIsActive = IsDebuggerPresent () || (tr_getLog ()!=NULL);
    216 
    217     return deepLoggingIsActive != 0;
     218  static int8_t deepLoggingIsActive = -1;
     219
     220  if (deepLoggingIsActive < 0)
     221    deepLoggingIsActive = IsDebuggerPresent () || (tr_getLog ()!=NULL);
     222
     223  return deepLoggingIsActive != 0;
    218224}
    219225
     
    225231            ...)
    226232{
    227     FILE * fp = tr_getLog ();
    228     if (fp || IsDebuggerPresent ())
    229     {
    230         va_list          args;
    231         char              timestr[64];
    232         struct evbuffer * buf = evbuffer_new ();
    233         char *            base = tr_basename (file);
    234         char *            message;
    235 
    236         evbuffer_add_printf (buf, "[%s] ",
    237                             tr_getLogTimeStr (timestr, sizeof (timestr)));
    238         if (name)
    239             evbuffer_add_printf (buf, "%s ", name);
    240         va_start (args, fmt);
    241         evbuffer_add_vprintf (buf, fmt, args);
    242         va_end (args);
    243         evbuffer_add_printf (buf, " (%s:%d)\n", base, line);
    244         /* FIXME (libevent2) ifdef this out for nonwindows platforms */
    245         message = evbuffer_free_to_str (buf);
    246         OutputDebugString (message);
    247         if (fp)
    248             fputs (message, fp);
    249 
    250         tr_free (message);
    251         tr_free (base);
     233  FILE * fp = tr_getLog ();
     234  if (fp || IsDebuggerPresent ())
     235    {
     236      va_list args;
     237      char timestr[64];
     238      char * message;
     239      struct evbuffer * buf = evbuffer_new ();
     240      char * base = tr_basename (file);
     241
     242      evbuffer_add_printf (buf, "[%s] ",
     243                           tr_getLogTimeStr (timestr, sizeof (timestr)));
     244      if (name)
     245        evbuffer_add_printf (buf, "%s ", name);
     246      va_start (args, fmt);
     247      evbuffer_add_vprintf (buf, fmt, args);
     248      va_end (args);
     249      evbuffer_add_printf (buf, " (%s:%d)\n", base, line);
     250      /* FIXME (libevent2) ifdef this out for nonwindows platforms */
     251      message = evbuffer_free_to_str (buf);
     252      OutputDebugString (message);
     253      if (fp)
     254        fputs (message, fp);
     255
     256      tr_free (message);
     257      tr_free (base);
    252258    }
    253259}
     
    263269        const char * fmt, ...)
    264270{
    265     const int err = errno; /* message logging shouldn't affect errno */
    266     char buf[1024];
    267     va_list ap;
    268     tr_lockLock (getMessageLock ());
    269 
    270     /* build the text message */
    271     *buf = '\0';
    272     va_start (ap, fmt);
    273     evutil_vsnprintf (buf, sizeof (buf), fmt, ap);
    274     va_end (ap);
    275 
    276     OutputDebugString (buf);
    277 
    278     if (*buf)
    279     {
    280         if (messageQueuing)
     271  const int err = errno; /* message logging shouldn't affect errno */
     272  char buf[1024];
     273  va_list ap;
     274  tr_lockLock (getMessageLock ());
     275
     276  /* build the text message */
     277  *buf = '\0';
     278  va_start (ap, fmt);
     279  evutil_vsnprintf (buf, sizeof (buf), fmt, ap);
     280  va_end (ap);
     281
     282  OutputDebugString (buf);
     283
     284  if (*buf)
     285    {
     286      if (messageQueuing)
    281287        {
    282             tr_msg_list * newmsg;
    283             newmsg = tr_new0 (tr_msg_list, 1);
    284             newmsg->level = level;
    285             newmsg->when = tr_time ();
    286             newmsg->message = tr_strdup (buf);
    287             newmsg->file = file;
    288             newmsg->line = line;
    289             newmsg->name = tr_strdup (name);
    290 
    291             *messageQueueTail = newmsg;
    292             messageQueueTail = &newmsg->next;
    293             ++messageQueueCount;
    294 
    295             if (messageQueueCount > TR_MAX_MSG_LOG)
     288          tr_msg_list * newmsg;
     289          newmsg = tr_new0 (tr_msg_list, 1);
     290          newmsg->level = level;
     291          newmsg->when = tr_time ();
     292          newmsg->message = tr_strdup (buf);
     293          newmsg->file = file;
     294          newmsg->line = line;
     295          newmsg->name = tr_strdup (name);
     296
     297          *messageQueueTail = newmsg;
     298          messageQueueTail = &newmsg->next;
     299          ++messageQueueCount;
     300
     301          if (messageQueueCount > TR_MAX_MSG_LOG)
    296302            {
    297                 tr_msg_list * old = messageQueue;
    298                 messageQueue = old->next;
    299                 old->next = NULL;
    300                 tr_freeMessageList (old);
    301 
    302                 --messageQueueCount;
    303 
    304                 assert (messageQueueCount == TR_MAX_MSG_LOG);
     303              tr_msg_list * old = messageQueue;
     304              messageQueue = old->next;
     305              old->next = NULL;
     306              tr_freeMessageList (old);
     307              --messageQueueCount;
     308              assert (messageQueueCount == TR_MAX_MSG_LOG);
    305309            }
    306310        }
    307         else
     311      else
    308312        {
    309             char timestr[64];
    310             FILE * fp;
    311 
    312             fp = tr_getLog ();
    313             if (fp == NULL)
    314                 fp = stderr;
    315 
    316             tr_getLogTimeStr (timestr, sizeof (timestr));
    317 
    318             if (name)
    319                 fprintf (fp, "[%s] %s: %s\n", timestr, name, buf);
    320             else
    321                 fprintf (fp, "[%s] %s\n", timestr, buf);
    322             fflush (fp);
     313          FILE * fp;
     314          char timestr[64];
     315
     316          fp = tr_getLog ();
     317          if (fp == NULL)
     318            fp = stderr;
     319
     320          tr_getLogTimeStr (timestr, sizeof (timestr));
     321
     322          if (name)
     323            fprintf (fp, "[%s] %s: %s\n", timestr, name, buf);
     324          else
     325            fprintf (fp, "[%s] %s\n", timestr, buf);
     326          fflush (fp);
    323327        }
    324328    }
    325329
    326     tr_lockUnlock (getMessageLock ());
    327     errno = err;
     330  tr_lockUnlock (getMessageLock ());
     331  errno = err;
    328332}
    329333
     
    335339tr_malloc (size_t size)
    336340{
    337     return size ? malloc (size) : NULL;
     341  return size ? malloc (size) : NULL;
    338342}
    339343
     
    341345tr_malloc0 (size_t size)
    342346{
    343     return size ? calloc (1, size) : NULL;
     347  return size ? calloc (1, size) : NULL;
    344348}
    345349
     
    347351tr_free (void * p)
    348352{
    349     if (p != NULL)
    350         free (p);
     353  if (p != NULL)
     354    free (p);
    351355}
    352356
     
    354358tr_memdup (const void * src, size_t byteCount)
    355359{
    356     return memcpy (tr_malloc (byteCount), src, byteCount);
     360  return memcpy (tr_malloc (byteCount), src, byteCount);
    357361}
    358362
     
    364368tr_strip_positional_args (const char* str)
    365369{
    366     const char * in = str;
    367     static size_t bufsize = 0;
    368     static char * buf = NULL;
    369     const size_t  len = str ? strlen (str) : 0;
    370     char *        out;
    371 
    372     if (!buf || (bufsize < len))
    373     {
    374         bufsize = len * 2 + 1;
    375         buf = tr_renew (char, buf, bufsize);
    376     }
    377 
    378     for (out = buf; str && *str; ++str)
    379     {
    380         *out++ = *str;
    381 
    382         if ((*str == '%') && isdigit (str[1]))
     370  char * out;
     371  static size_t bufsize = 0;
     372  static char * buf = NULL;
     373  const char * in = str;
     374  const size_t  len = str ? strlen (str) : 0;
     375
     376  if (!buf || (bufsize < len))
     377    {
     378      bufsize = len * 2 + 1;
     379      buf = tr_renew (char, buf, bufsize);
     380    }
     381
     382  for (out = buf; str && *str; ++str)
     383    {
     384      *out++ = *str;
     385
     386      if ((*str == '%') && isdigit (str[1]))
    383387        {
    384             const char * tmp = str + 1;
    385             while (isdigit (*tmp))
    386                 ++tmp;
    387             if (*tmp == '$')
    388                 str = tmp[1]=='\'' ? tmp+1 : tmp;
     388          const char * tmp = str + 1;
     389          while (isdigit (*tmp))
     390            ++tmp;
     391          if (*tmp == '$')
     392            str = tmp[1]=='\'' ? tmp+1 : tmp;
    389393        }
    390394
    391         if ((*str == '%') && (str[1] == '\''))
    392             str = str + 1;
    393 
    394     }
    395     *out = '\0';
    396 
    397     return !in || strcmp (buf, in) ? buf : in;
     395      if ((*str == '%') && (str[1] == '\''))
     396        str = str + 1;
     397
     398    }
     399
     400  *out = '\0';
     401  return !in || strcmp (buf, in) ? buf : in;
    398402}
    399403
     
    405409tr_timerAdd (struct event * timer, int seconds, int microseconds)
    406410{
    407     struct timeval tv;
    408     tv.tv_sec = seconds;
    409     tv.tv_usec = microseconds;
    410 
    411     assert (tv.tv_sec >= 0);
    412     assert (tv.tv_usec >= 0);
    413     assert (tv.tv_usec < 1000000);
    414 
    415     evtimer_add (timer, &tv);
     411  struct timeval tv;
     412  tv.tv_sec = seconds;
     413  tv.tv_usec = microseconds;
     414
     415  assert (tv.tv_sec >= 0);
     416  assert (tv.tv_usec >= 0);
     417  assert (tv.tv_usec < 1000000);
     418
     419  evtimer_add (timer, &tv);
    416420}
    417421
     
    419423tr_timerAddMsec (struct event * timer, int msec)
    420424{
    421     const int seconds =  msec / 1000;
    422     const int usec = (msec%1000) * 1000;
    423     tr_timerAdd (timer, seconds, usec);
     425  const int seconds =  msec / 1000;
     426  const int usec = (msec%1000) * 1000;
     427  tr_timerAdd (timer, seconds, usec);
    424428}
    425429
     
    430434uint8_t *
    431435tr_loadFile (const char * path,
    432              size_t *    size)
    433 {
    434     uint8_t * buf;
    435     struct stat  sb;
    436     int fd;
    437     ssize_t n;
    438     const char * const err_fmt = _("Couldn't read \"%1$s\": %2$s");
    439 
    440     /* try to stat the file */
    441     errno = 0;
    442     if (stat (path, &sb))
    443     {
    444         const int err = errno;
    445         tr_dbg (err_fmt, path, tr_strerror (errno));
    446         errno = err;
    447         return NULL;
    448     }
    449 
    450     if ((sb.st_mode & S_IFMT) != S_IFREG)
    451     {
    452         tr_err (err_fmt, path, _("Not a regular file"));
    453         errno = EISDIR;
    454         return NULL;
    455     }
    456 
    457     /* Load the torrent file into our buffer */
    458     fd = tr_open_file_for_scanning (path);
    459     if (fd < 0)
    460     {
    461         const int err = errno;
    462         tr_err (err_fmt, path, tr_strerror (errno));
    463         errno = err;
    464         return NULL;
    465     }
    466     buf = tr_malloc (sb.st_size + 1);
    467     if (!buf)
    468     {
    469         const int err = errno;
    470         tr_err (err_fmt, path, _("Memory allocation failed"));
    471         tr_close_file (fd);
    472         errno = err;
    473         return NULL;
    474     }
    475     n = read (fd, buf, (size_t)sb.st_size);
    476     if (n == -1)
    477     {
    478         const int err = errno;
    479         tr_err (err_fmt, path, tr_strerror (errno));
    480         tr_close_file (fd);
    481         free (buf);
    482         errno = err;
    483         return NULL;
    484     }
    485 
    486     tr_close_file (fd);
    487     buf[ sb.st_size ] = '\0';
    488     *size = sb.st_size;
    489     return buf;
     436             size_t     * size)
     437{
     438  uint8_t * buf;
     439  struct stat  sb;
     440  int fd;
     441  ssize_t n;
     442  const char * const err_fmt = _("Couldn't read \"%1$s\": %2$s");
     443
     444  /* try to stat the file */
     445  errno = 0;
     446  if (stat (path, &sb))
     447    {
     448      const int err = errno;
     449      tr_dbg (err_fmt, path, tr_strerror (errno));
     450      errno = err;
     451      return NULL;
     452    }
     453
     454  if ((sb.st_mode & S_IFMT) != S_IFREG)
     455    {
     456      tr_err (err_fmt, path, _("Not a regular file"));
     457      errno = EISDIR;
     458      return NULL;
     459    }
     460
     461  /* Load the torrent file into our buffer */
     462  fd = tr_open_file_for_scanning (path);
     463  if (fd < 0)
     464    {
     465      const int err = errno;
     466      tr_err (err_fmt, path, tr_strerror (errno));
     467      errno = err;
     468      return NULL;
     469    }
     470  buf = tr_malloc (sb.st_size + 1);
     471  if (!buf)
     472    {
     473      const int err = errno;
     474      tr_err (err_fmt, path, _("Memory allocation failed"));
     475      tr_close_file (fd);
     476      errno = err;
     477      return NULL;
     478    }
     479  n = read (fd, buf, (size_t)sb.st_size);
     480  if (n == -1)
     481    {
     482      const int err = errno;
     483      tr_err (err_fmt, path, tr_strerror (errno));
     484      tr_close_file (fd);
     485      free (buf);
     486      errno = err;
     487      return NULL;
     488    }
     489
     490  tr_close_file (fd);
     491  buf[ sb.st_size ] = '\0';
     492  *size = sb.st_size;
     493  return buf;
    490494}
    491495
     
    493497tr_basename (const char * path)
    494498{
    495     char * tmp = tr_strdup (path);
    496     char * ret = tr_strdup (basename (tmp));
    497     tr_free (tmp);
    498     return ret;
     499  char * tmp = tr_strdup (path);
     500  char * ret = tr_strdup (basename (tmp));
     501  tr_free (tmp);
     502  return ret;
    499503}
    500504
     
    502506tr_dirname (const char * path)
    503507{
    504     char * tmp = tr_strdup (path);
    505     char * ret = tr_strdup (dirname (tmp));
    506     tr_free (tmp);
    507     return ret;
     508  char * tmp = tr_strdup (path);
     509  char * ret = tr_strdup (dirname (tmp));
     510  tr_free (tmp);
     511  return ret;
    508512}
    509513
     
    512516{
    513517#ifdef HAVE_MKDTEMP
    514     return mkdtemp (template);
     518  return mkdtemp (template);
    515519#else
    516     if (!mktemp (template) || mkdir (template, 0700))
    517         return NULL;
    518     return template;
     520  if (!mktemp (template) || mkdir (template, 0700))
     521    return NULL;
     522  return template;
    519523#endif
    520524}
     
    533537{
    534538#ifdef WIN32
    535     if (path && isalpha (path[0]) && path[1] == ':' && !path[2])
    536         return 0;
    537     return mkdir (path);
     539  if (path && isalpha (path[0]) && path[1] == ':' && !path[2])
     540    return 0;
     541  return mkdir (path);
    538542#else
    539     return mkdir (path, permissions);
     543  return mkdir (path, permissions);
    540544#endif
    541545}
     
    545549           int          permissions)
    546550{
    547     char *      path = tr_strdup (path_in);
    548     char *      p, * pp;
    549     struct stat sb;
    550     bool        done;
    551     int         tmperr;
    552     int         rv;
    553 
    554     /* walk past the root */
    555     p = path;
    556     while (*p == TR_PATH_DELIMITER)
    557         ++p;
    558 
    559     pp = p;
    560     done = false;
    561     while ((p = strchr (pp, TR_PATH_DELIMITER)) || (p = strchr (pp, '\0')))
    562     {
    563         if (!*p)
    564             done = true;
    565         else
    566             *p = '\0';
    567 
    568         tmperr = errno;
    569         rv = stat (path, &sb);
    570         errno = tmperr;
    571         if (rv)
     551  char * p;
     552  char * pp;
     553  bool done;
     554  int tmperr;
     555  int rv;
     556  struct stat sb;
     557  char * path = tr_strdup (path_in);
     558
     559  /* walk past the root */
     560  p = path;
     561  while (*p == TR_PATH_DELIMITER)
     562    ++p;
     563
     564  pp = p;
     565  done = false;
     566  while ((p = strchr (pp, TR_PATH_DELIMITER)) || (p = strchr (pp, '\0')))
     567    {
     568      if (!*p)
     569        done = true;
     570      else
     571        *p = '\0';
     572
     573      tmperr = errno;
     574      rv = stat (path, &sb);
     575      errno = tmperr;
     576      if (rv)
    572577        {
    573             /* Folder doesn't exist yet */
    574             if (tr_mkdir (path, permissions))
     578          /* Folder doesn't exist yet */
     579          if (tr_mkdir (path, permissions))
    575580            {
    576                 tmperr = errno;
    577                 tr_err (_("Couldn't create \"%1$s\": %2$s"), path, tr_strerror (tmperr));
    578                 tr_free (path);
    579                 errno = tmperr;
    580                 return -1;
     581              tmperr = errno;
     582              tr_err (_("Couldn't create \"%1$s\": %2$s"), path, tr_strerror (tmperr));
     583              tr_free (path);
     584              errno = tmperr;
     585              return -1;
    581586            }
    582587        }
    583         else if ((sb.st_mode & S_IFMT) != S_IFDIR)
     588      else if ((sb.st_mode & S_IFMT) != S_IFDIR)
    584589        {
    585             /* Node exists but isn't a folder */
    586             char * buf = tr_strdup_printf (_("File \"%s\" is in the way"), path);
    587             tr_err (_("Couldn't create \"%1$s\": %2$s"), path_in, buf);
    588             tr_free (buf);
    589             tr_free (path);
    590             errno = ENOTDIR;
    591             return -1;
     590          /* Node exists but isn't a folder */
     591          char * buf = tr_strdup_printf (_("File \"%s\" is in the way"), path);
     592          tr_err (_("Couldn't create \"%1$s\": %2$s"), path_in, buf);
     593          tr_free (buf);
     594          tr_free (path);
     595          errno = ENOTDIR;
     596          return -1;
    592597        }
    593598
    594         if (done)
    595             break;
    596 
    597         *p = TR_PATH_DELIMITER;
    598         p++;
    599         pp = p;
    600     }
    601 
    602     tr_free (path);
    603     return 0;
     599      if (done)
     600        break;
     601
     602      *p = TR_PATH_DELIMITER;
     603      p++;
     604      pp = p;
     605    }
     606
     607  tr_free (path);
     608  return 0;
    604609}
    605610
     
    607612tr_buildPath (const char *first_element, ...)
    608613{
    609     size_t bufLen = 0;
    610     const char * element;
    611     char * buf;
    612     char * pch;
    613     va_list vl;
    614 
    615     /* pass 1: allocate enough space for the string */
    616     va_start (vl, first_element);
    617     element = first_element;
    618     while (element) {
    619         bufLen += strlen (element) + 1;
    620         element = va_arg (vl, const char*);
    621     }
    622     pch = buf = tr_new (char, bufLen);
    623     va_end (vl);
    624 
    625     /* pass 2: build the string piece by piece */
    626     va_start (vl, first_element);
    627     element = first_element;
    628     while (element) {
    629         const size_t elementLen = strlen (element);
    630         memcpy (pch, element, elementLen);
    631         pch += elementLen;
    632         *pch++ = TR_PATH_DELIMITER;
    633         element = va_arg (vl, const char*);
    634     }
    635     va_end (vl);
    636 
    637     /* terminate the string. if nonempty, eat the unwanted trailing slash */
    638     if (pch != buf)
    639         --pch;
    640     *pch++ = '\0';
    641 
    642     /* sanity checks & return */
    643     assert (pch - buf == (off_t)bufLen);
    644     return buf;
     614  const char * element;
     615  char * buf;
     616  char * pch;
     617  va_list vl;
     618  size_t bufLen = 0;
     619
     620  /* pass 1: allocate enough space for the string */
     621  va_start (vl, first_element);
     622  element = first_element;
     623  while (element)
     624    {
     625      bufLen += strlen (element) + 1;
     626      element = va_arg (vl, const char*);
     627    }
     628  pch = buf = tr_new (char, bufLen);
     629  va_end (vl);
     630
     631  /* pass 2: build the string piece by piece */
     632  va_start (vl, first_element);
     633  element = first_element;
     634  while (element)
     635    {
     636      const size_t elementLen = strlen (element);
     637      memcpy (pch, element, elementLen);
     638      pch += elementLen;
     639      *pch++ = TR_PATH_DELIMITER;
     640      element = va_arg (vl, const char*);
     641    }
     642  va_end (vl);
     643
     644  /* terminate the string. if nonempty, eat the unwanted trailing slash */
     645  if (pch != buf)
     646    --pch;
     647  *pch++ = '\0';
     648
     649  /* sanity checks & return */
     650  assert (pch - buf == (off_t)bufLen);
     651  return buf;
    645652}
    646653
     
    654661tr_fileExists (const char * filename, time_t * mtime)
    655662{
    656     struct stat sb;
    657     const bool ok = !stat (filename, &sb);
    658 
    659     if (ok && (mtime != NULL))
    660         *mtime = TR_STAT_MTIME (sb);
    661 
    662     return ok;
     663  struct stat sb;
     664  const bool ok = !stat (filename, &sb);
     665
     666  if (ok && (mtime != NULL))
     667    *mtime = TR_STAT_MTIME (sb);
     668
     669  return ok;
    663670}
    664671
     
    670677evbuffer_free_to_str (struct evbuffer * buf)
    671678{
    672     const size_t n = evbuffer_get_length (buf);
    673     char * ret = tr_new (char, n + 1);
    674     evbuffer_copyout (buf, ret, n);
    675     evbuffer_free (buf);
    676     ret[n] = '\0';
    677     return ret;
     679  const size_t n = evbuffer_get_length (buf);
     680  char * ret = tr_new (char, n + 1);
     681  evbuffer_copyout (buf, ret, n);
     682  evbuffer_free (buf);
     683  ret[n] = '\0';
     684  return ret;
    678685}
    679686
     
    681688tr_strdup (const void * in)
    682689{
    683     return tr_strndup (in, in ? (int)strlen ((const char *)in) : 0);
     690  return tr_strndup (in, in ? (int)strlen ((const char *)in) : 0);
    684691}
    685692
     
    687694tr_strndup (const void * in, int len)
    688695{
    689     char * out = NULL;
    690 
    691     if (len < 0)
    692     {
    693         out = tr_strdup (in);
    694     }
    695     else if (in)
    696     {
    697         out = tr_malloc (len + 1);
    698         memcpy (out, in, len);
    699         out[len] = '\0';
    700     }
    701 
    702     return out;
     696  char * out = NULL;
     697
     698  if (len < 0)
     699    {
     700      out = tr_strdup (in);
     701    }
     702  else if (in)
     703    {
     704      out = tr_malloc (len + 1);
     705      memcpy (out, in, len);
     706      out[len] = '\0';
     707    }
     708
     709  return out;
    703710}
    704711
     
    708715{
    709716#ifdef HAVE_MEMMEM
    710     return memmem (haystack, haystacklen, needle, needlelen);
     717  return memmem (haystack, haystacklen, needle, needlelen);
    711718#else
    712     size_t i;
    713     if (!needlelen)
    714         return haystack;
    715     if (needlelen > haystacklen || !haystack || !needle)
    716         return NULL;
    717     for (i=0; i<=haystacklen-needlelen; ++i)
    718         if (!memcmp (haystack+i, needle, needlelen))
    719             return haystack+i;
     719  size_t i;
     720  if (!needlelen)
     721    return haystack;
     722  if (needlelen > haystacklen || !haystack || !needle)
    720723    return NULL;
     724  for (i=0; i<=haystacklen-needlelen; ++i)
     725    if (!memcmp (haystack+i, needle, needlelen))
     726      return haystack+i;
     727  return NULL;
    721728#endif
    722729}
     
    725732tr_strdup_printf (const char * fmt, ...)
    726733{
    727     va_list ap;
    728     char * ret;
    729     size_t len;
    730     char statbuf[2048];
    731 
    732     va_start (ap, fmt);
    733     len = evutil_vsnprintf (statbuf, sizeof (statbuf), fmt, ap);
    734     va_end (ap);
    735     if (len < sizeof (statbuf))
    736         ret = tr_strndup (statbuf, len);
    737     else {
    738         ret = tr_new (char, len + 1);
    739         va_start (ap, fmt);
    740         evutil_vsnprintf (ret, len + 1, fmt, ap);
    741         va_end (ap);
    742     }
    743 
    744     return ret;
     734  va_list ap;
     735  char * ret;
     736  size_t len;
     737  char statbuf[2048];
     738
     739  va_start (ap, fmt);
     740  len = evutil_vsnprintf (statbuf, sizeof (statbuf), fmt, ap);
     741  va_end (ap);
     742
     743  if (len < sizeof (statbuf))
     744    {
     745      ret = tr_strndup (statbuf, len);
     746    }
     747  else
     748    {
     749      ret = tr_new (char, len + 1);
     750      va_start (ap, fmt);
     751      evutil_vsnprintf (ret, len + 1, fmt, ap);
     752      va_end (ap);
     753    }
     754
     755  return ret;
    745756}
    746757
     
    748759tr_strerror (int i)
    749760{
    750     const char * ret = strerror (i);
    751 
    752     if (ret == NULL)
    753         ret = "Unknown Error";
    754     return ret;
     761  const char * ret = strerror (i);
     762
     763  if (ret == NULL)
     764    ret = "Unknown Error";
     765
     766  return ret;
    755767}
    756768
     
    758770tr_strcmp0 (const char * str1, const char * str2)
    759771{
    760     if (str1 && str2) return strcmp (str1, str2);
    761     if (str1) return 1;
    762     if (str2) return -1;
    763     return 0;
     772  if (str1 && str2) return strcmp (str1, str2);
     773  if (str1) return 1;
     774  if (str2) return -1;
     775  return 0;
    764776}
    765777
     
    773785{
    774786#ifdef HAVE_STRSEP
    775     return strsep (str, delims);
     787  return strsep (str, delims);
    776788#else
    777     char *token;
    778 
    779     if (*str == NULL) {
    780         /* No more tokens */
    781         return NULL;
    782     }
    783 
    784     token = *str;
    785     while (**str != '\0') {
    786         if (strchr (delims, **str) != NULL) {
    787             **str = '\0';
     789  char *token;
     790
     791  if (*str == NULL) /* no more tokens */
     792    return NULL;
     793
     794  token = *str;
     795  while (**str != '\0')
     796    {
     797      if (strchr (delims, **str) != NULL)
     798        {
     799          **str = '\0';
    788800          (*str)++;
    789801            return token;
     
    792804    }
    793805
    794     /* There is not another token */
    795     *str = NULL;
    796 
    797     return token;
     806  /* there is not another token */
     807  *str = NULL;
     808
     809  return token;
    798810#endif
    799811}
     
    802814tr_strstrip (char * str)
    803815{
    804     if (str != NULL)
    805     {
    806         size_t pos;
    807         size_t len = strlen (str);
    808 
    809         while (len && isspace (str[len - 1]))
    810             --len;
    811 
    812         for (pos = 0; pos < len && isspace (str[pos]);)
    813             ++pos;
    814 
    815         len -= pos;
    816         memmove (str, str + pos, len);
    817         str[len] = '\0';
    818     }
    819 
    820     return str;
     816  if (str != NULL)
     817    {
     818      size_t pos;
     819      size_t len = strlen (str);
     820
     821      while (len && isspace (str[len - 1]))
     822        --len;
     823
     824      for (pos = 0; pos < len && isspace (str[pos]);)
     825        ++pos;
     826
     827      len -= pos;
     828      memmove (str, str + pos, len);
     829      str[len] = '\0';
     830    }
     831
     832  return str;
    821833}
    822834
     
    824836tr_str_has_suffix (const char *str, const char *suffix)
    825837{
    826     size_t str_len;
    827     size_t suffix_len;
    828 
    829     if (!str)
    830         return false;
    831     if (!suffix)
    832         return true;
    833 
    834     str_len = strlen (str);
    835     suffix_len = strlen (suffix);
    836     if (str_len < suffix_len)
    837         return false;
    838 
    839     return !evutil_ascii_strncasecmp (str + str_len - suffix_len, suffix, suffix_len);
     838  size_t str_len;
     839  size_t suffix_len;
     840
     841  if (!str)
     842    return false;
     843  if (!suffix)
     844    return true;
     845
     846  str_len = strlen (str);
     847  suffix_len = strlen (suffix);
     848  if (str_len < suffix_len)
     849    return false;
     850
     851  return !evutil_ascii_strncasecmp (str + str_len - suffix_len, suffix, suffix_len);
    840852}
    841853
     
    847859tr_time_msec (void)
    848860{
    849     struct timeval tv;
    850 
    851     gettimeofday (&tv, NULL);
    852     return (uint64_t) tv.tv_sec * 1000 + (tv.tv_usec / 1000);
     861  struct timeval tv;
     862
     863  gettimeofday (&tv, NULL);
     864  return (uint64_t) tv.tv_sec * 1000 + (tv.tv_usec / 1000);
    853865}
    854866
     
    857869{
    858870#ifdef WIN32
    859     Sleep ((DWORD)msec);
     871  Sleep ((DWORD)msec);
    860872#else
    861     struct timespec ts;
    862     ts.tv_sec = msec / 1000;
    863     ts.tv_nsec = (msec % 1000) * 1000000;
    864     nanosleep (&ts, NULL);
     873  struct timespec ts;
     874  ts.tv_sec = msec / 1000;
     875  ts.tv_nsec = (msec % 1000) * 1000000;
     876  nanosleep (&ts, NULL);
    865877#endif
    866878}
     
    873885tr_snprintf (char * buf, size_t buflen, const char * fmt, ...)
    874886{
    875     int    len;
    876     va_list args;
    877 
    878     va_start (args, fmt);
    879     len = evutil_vsnprintf (buf, buflen, fmt, args);
    880     va_end (args);
    881     return len;
     887  int len;
     888  va_list args;
     889
     890  va_start (args, fmt);
     891  len = evutil_vsnprintf (buf, buflen, fmt, args);
     892  va_end (args);
     893  return len;
    882894}
    883895
     
    891903{
    892904#ifdef HAVE_STRLCPY
    893     return strlcpy (dst, src, siz);
     905  return strlcpy (dst, src, siz);
    894906#else
    895     char *      d = dst;
    896     const char *s = src;
    897     size_t      n = siz;
    898 
    899     assert (s);
    900     assert (d);
    901 
    902     /* Copy as many bytes as will fit */
    903     if (n != 0)
    904     {
    905         while (--n != 0)
     907  char *      d = dst;
     908  const char *s = src;
     909  size_t      n = siz;
     910
     911  assert (s);
     912  assert (d);
     913
     914  /* Copy as many bytes as will fit */
     915  if (n != 0)
     916    {
     917      while (--n != 0)
    906918        {
    907             if ((*d++ = *s++) == '\0')
    908                 break;
     919          if ((*d++ = *s++) == '\0')
     920            break;
    909921        }
    910922    }
    911923
    912     /* Not enough room in dst, add NUL and traverse rest of src */
    913     if (n == 0)
    914     {
    915         if (siz != 0)
    916             *d = '\0'; /* NUL-terminate dst */
    917         while (*s++)
    918             ;
    919     }
    920 
    921     return s - (char*)src - 1;  /* count does not include NUL */
     924  /* Not enough room in dst, add NUL and traverse rest of src */
     925  if (n == 0)
     926    {
     927      if (siz != 0)
     928        *d = '\0'; /* NUL-terminate dst */
     929      while (*s++)
     930        ;
     931    }
     932
     933  return s - (char*)src - 1;  /* count does not include NUL */
    922934#endif
    923935}
     
    930942tr_getRatio (uint64_t numerator, uint64_t denominator)
    931943{
    932     double ratio;
    933 
    934     if (denominator > 0)
    935         ratio = numerator / (double)denominator;
    936     else if (numerator > 0)
    937         ratio = TR_RATIO_INF;
    938     else
    939         ratio = TR_RATIO_NA;
    940 
    941     return ratio;
     944  double ratio;
     945
     946  if (denominator > 0)
     947    ratio = numerator / (double)denominator;
     948  else if (numerator > 0)
     949    ratio = TR_RATIO_INF;
     950  else
     951    ratio = TR_RATIO_NA;
     952
     953  return ratio;
    942954}
    943955
     
    945957tr_sha1_to_hex (char * out, const uint8_t * sha1)
    946958{
    947     int i;
    948     static const char hex[] = "0123456789abcdef";
    949 
    950     for (i=0; i<20; ++i)
    951     {
    952         const unsigned int val = *sha1++;
    953         *out++ = hex[val >> 4];
    954         *out++ = hex[val & 0xf];
    955     }
    956 
    957     *out = '\0';
     959  int i;
     960  static const char hex[] = "0123456789abcdef";
     961
     962  for (i=0; i<20; ++i)
     963    {
     964      const unsigned int val = *sha1++;
     965      *out++ = hex[val >> 4];
     966      *out++ = hex[val & 0xf];
     967    }
     968
     969  *out = '\0';
    958970}
    959971
     
    961973tr_hex_to_sha1 (uint8_t * out, const char * in)
    962974{
    963     int i;
    964     static const char hex[] = "0123456789abcdef";
    965 
    966     for (i=0; i<20; ++i)
    967     {
    968         const int hi = strchr (hex, tolower (*in++)) - hex;
    969         const int lo = strchr (hex, tolower (*in++)) - hex;
    970         *out++ = (uint8_t)((hi<<4) | lo);
     975  int i;
     976  static const char hex[] = "0123456789abcdef";
     977
     978  for (i=0; i<20; ++i)
     979    {
     980      const int hi = strchr (hex, tolower (*in++)) - hex;
     981      const int lo = strchr (hex, tolower (*in++)) - hex;
     982      *out++ = (uint8_t)((hi<<4) | lo);
    971983    }
    972984}
     
    979991isValidURLChars (const char * url, int url_len)
    980992{
    981     const char * c;
    982     const char * end;
    983     static const char * rfc2396_valid_chars =
    984         "abcdefghijklmnopqrstuvwxyz" /* lowalpha */
    985         "ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* upalpha */
    986         "0123456789"                 /* digit */
    987         "-_.!~*'()"                  /* mark */
    988         ";/?:@&=+$,"                 /* reserved */
    989         "<>#%<\""                    /* delims */
    990         "{}|\\^[]`";                 /* unwise */
    991 
    992     if (url == NULL)
    993         return false;
    994 
    995     for (c=url, end=c+url_len; c && *c && c!=end; ++c)
    996         if (!strchr (rfc2396_valid_chars, *c))
    997             return false;
    998 
    999     return true;
     993  const char * c;
     994  const char * end;
     995  static const char * rfc2396_valid_chars =
     996    "abcdefghijklmnopqrstuvwxyz" /* lowalpha */
     997    "ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* upalpha */
     998    "0123456789"                 /* digit */
     999    "-_.!~*'()"                  /* mark */
     1000    ";/?:@&=+$,"                 /* reserved */
     1001    "<>#%<\""                    /* delims */
     1002    "{}|\\^[]`";                 /* unwise */
     1003
     1004  if (url == NULL)
     1005    return false;
     1006
     1007  for (c=url, end=c+url_len; c && *c && c!=end; ++c)
     1008    if (!strchr (rfc2396_valid_chars, *c))
     1009      return false;
     1010
     1011  return true;
    10001012}
    10011013
     
    10041016tr_urlIsValidTracker (const char * url)
    10051017{
    1006     bool valid;
    1007 
    1008     if (url == NULL)
    1009     {
    1010         valid = false;
    1011     }
    1012     else
    1013     {
    1014         const int len = strlen (url);
    1015 
    1016         valid = isValidURLChars (url, len)
    1017             && !tr_urlParse (url, len, NULL, NULL, NULL, NULL)
    1018             && (!memcmp (url,"http://",7) || !memcmp (url,"https://",8) || !memcmp (url,"udp://",6));
    1019     }
    1020 
    1021     return valid;
     1018  bool valid;
     1019
     1020  if (url == NULL)
     1021    {
     1022      valid = false;
     1023    }
     1024  else
     1025    {
     1026      const int len = strlen (url);
     1027
     1028      valid = isValidURLChars (url, len)
     1029           && !tr_urlParse (url, len, NULL, NULL, NULL, NULL)
     1030           && (!memcmp (url,"http://",7) || !memcmp (url,"https://",8) || !memcmp (url,"udp://",6));
     1031    }
     1032
     1033  return valid;
    10221034}
    10231035
     
    10261038tr_urlIsValid (const char * url, int url_len)
    10271039{
    1028     bool valid;
    1029 
    1030     if (url == NULL)
    1031     {
    1032         valid = false;
    1033     }
    1034     else
    1035     {
    1036         if (url_len < 0)
    1037             url_len = strlen (url);
    1038 
    1039         valid = isValidURLChars (url, url_len)
    1040             && !tr_urlParse (url, url_len, NULL, NULL, NULL, NULL)
    1041             && (!memcmp (url,"http://",7) || !memcmp (url,"https://",8) || !memcmp (url,"ftp://",6) || !memcmp (url,"sftp://",7));
    1042     }
    1043 
    1044     return valid;
     1040  bool valid;
     1041
     1042  if (url == NULL)
     1043    {
     1044      valid = false;
     1045    }
     1046  else
     1047    {
     1048      if (url_len < 0)
     1049        url_len = strlen (url);
     1050
     1051      valid = isValidURLChars (url, url_len)
     1052           && !tr_urlParse (url, url_len, NULL, NULL, NULL, NULL)
     1053           && (!memcmp (url,"http://",7) || !memcmp (url,"https://",8) || !memcmp (url,"ftp://",6) || !memcmp (url,"sftp://",7));
     1054    }
     1055
     1056  return valid;
    10451057}
    10461058
     
    10481060tr_addressIsIP (const char * str)
    10491061{
    1050     tr_address tmp;
    1051     return tr_address_from_string (&tmp, str);
     1062  tr_address tmp;
     1063  return tr_address_from_string (&tmp, str);
    10521064}
    10531065
     
    10601072             char **      setme_path)
    10611073{
    1062     int          err;
    1063     int          port = 0;
    1064     int          n;
    1065     char *       tmp;
    1066     char *       pch;
    1067     size_t       host_len;
    1068     size_t       protocol_len;
    1069     const char * host = NULL;
    1070     const char * protocol = NULL;
    1071     const char * path = NULL;
    1072 
    1073     tmp = tr_strndup (url_in, len);
    1074     if ((pch = strstr (tmp, "://")))
    1075     {
    1076         *pch = '\0';
    1077         protocol = tmp;
    1078         protocol_len = pch - protocol;
    1079         pch += 3;
    1080 /*fprintf (stderr, "protocol is [%s]... what's left is [%s]\n", protocol, pch);*/
    1081         if ((n = strcspn (pch, ":/")))
     1074  int err;
     1075  int port = 0;
     1076  int n;
     1077  char * tmp;
     1078  char * pch;
     1079  size_t host_len;
     1080  size_t protocol_len;
     1081  const char * host = NULL;
     1082  const char * protocol = NULL;
     1083  const char * path = NULL;
     1084
     1085  tmp = tr_strndup (url_in, len);
     1086  if ((pch = strstr (tmp, "://")))
     1087    {
     1088      *pch = '\0';
     1089      protocol = tmp;
     1090      protocol_len = pch - protocol;
     1091      pch += 3;
     1092      if ((n = strcspn (pch, ":/")))
    10821093        {
    1083             const int havePort = pch[n] == ':';
    1084             host = pch;
    1085             host_len = n;
    1086             pch += n;
    1087             if (pch && *pch)
    1088                 *pch++ = '\0';
    1089 /*fprintf (stderr, "host is [%s]... what's left is [%s]\n", host, pch);*/
    1090             if (havePort)
     1094          const int havePort = pch[n] == ':';
     1095          host = pch;
     1096          host_len = n;
     1097          pch += n;
     1098          if (pch && *pch)
     1099            *pch++ = '\0';
     1100          if (havePort)
    10911101            {
    1092                 char * end;
    1093                 port = strtol (pch, &end, 10);
    1094                 pch = end;
    1095 /*fprintf (stderr, "port is [%d]... what's left is [%s]\n", port, pch);*/
     1102              char * end;
     1103              port = strtol (pch, &end, 10);
     1104              pch = end;
    10961105            }
    1097             path = pch;
    1098 /*fprintf (stderr, "path is [%s]\n", path);*/
     1106          path = pch;
    10991107        }
    11001108    }
    11011109
    1102     err = !host || !path || !protocol;
    1103 
    1104     if (!err && !port)
    1105     {
    1106         if (!strcmp (protocol, "udp")) port = 80;
    1107         else if (!strcmp (protocol, "ftp")) port = 21;
    1108         else if (!strcmp (protocol, "sftp")) port = 22;
    1109         else if (!strcmp (protocol, "http")) port = 80;
    1110         else if (!strcmp (protocol, "https")) port = 443;
    1111     }
    1112 
    1113     if (!err)
    1114     {
    1115         if (setme_protocol) *setme_protocol = tr_strndup (protocol, protocol_len);
    1116 
    1117         if (setme_host){ ((char*)host)[-3] = ':'; *setme_host =
    1118                               tr_strndup (host, host_len); }
    1119         if (setme_path){ if (!*path) *setme_path = tr_strdup ("/");
    1120                           else if (path[0] == '/') *setme_path = tr_strdup (path);
    1121                           else { ((char*)path)[-1] = '/'; *setme_path = tr_strdup (path - 1); } }
    1122         if (setme_port) *setme_port = port;
    1123     }
    1124 
    1125 
    1126     tr_free (tmp);
    1127     return err;
     1110  err = !host || !path || !protocol;
     1111
     1112  if (!err && !port)
     1113    {
     1114      if (!strcmp (protocol, "udp")) port = 80;
     1115      else if (!strcmp (protocol, "ftp")) port = 21;
     1116      else if (!strcmp (protocol, "sftp")) port = 22;
     1117      else if (!strcmp (protocol, "http")) port = 80;
     1118      else if (!strcmp (protocol, "https")) port = 443;
     1119    }
     1120
     1121  if (!err)
     1122    {
     1123      if (setme_protocol) *setme_protocol = tr_strndup (protocol, protocol_len);
     1124
     1125      if (setme_host){ ((char*)host)[-3] = ':'; *setme_host =
     1126                        tr_strndup (host, host_len); }
     1127
     1128      if (setme_path){ if (!*path) *setme_path = tr_strdup ("/");
     1129                       else if (path[0] == '/') *setme_path = tr_strdup (path);
     1130                       else { ((char*)path)[-1] = '/'; *setme_path = tr_strdup (path - 1); } }
     1131
     1132      if (setme_port) *setme_port = port;
     1133    }
     1134
     1135
     1136  tr_free (tmp);
     1137  return err;
    11281138}
    11291139
     
    11381148tr_base64_encode (const void * input, int length, int * setme_len)
    11391149{
    1140     int retlen = 0;
    1141     char * ret = NULL;
    1142 
    1143     if (input != NULL)
    1144     {
    1145         BIO * b64;
    1146         BIO * bmem;
    1147         BUF_MEM * bptr;
    1148 
    1149         if (length < 1)
    1150             length = (int)strlen (input);
    1151 
    1152         bmem = BIO_new (BIO_s_mem ());
    1153         b64 = BIO_new (BIO_f_base64 ());
    1154         BIO_set_flags (b64, BIO_FLAGS_BASE64_NO_NL);
    1155         b64 = BIO_push (b64, bmem);
    1156         BIO_write (b64, input, length);
     1150  int retlen = 0;
     1151  char * ret = NULL;
     1152
     1153  if (input != NULL)
     1154    {
     1155      BIO * b64;
     1156      BIO * bmem;
     1157      BUF_MEM * bptr;
     1158
     1159      if (length < 1)
     1160        length = (int)strlen (input);
     1161
     1162      bmem = BIO_new (BIO_s_mem ());
     1163      b64 = BIO_new (BIO_f_base64 ());
     1164      BIO_set_flags (b64, BIO_FLAGS_BASE64_NO_NL);
     1165      b64 = BIO_push (b64, bmem);
     1166      BIO_write (b64, input, length);
    11571167      (void) BIO_flush (b64);
    1158         BIO_get_mem_ptr (b64, &bptr);
    1159         ret = tr_strndup (bptr->data, bptr->length);
    1160         retlen = bptr->length;
    1161         BIO_free_all (b64);
    1162     }
    1163 
    1164     if (setme_len)
    1165         *setme_len = retlen;
    1166 
    1167     return ret;
     1168      BIO_get_mem_ptr (b64, &bptr);
     1169      ret = tr_strndup (bptr->data, bptr->length);
     1170      retlen = bptr->length;
     1171      BIO_free_all (b64);
     1172    }
     1173
     1174  if (setme_len)
     1175    *setme_len = retlen;
     1176
     1177  return ret;
    11681178}
    11691179
     
    11731183                  int *        setme_len)
    11741184{
    1175     char * ret;
    1176     BIO * b64;
    1177     BIO * bmem;
    1178     int    retlen;
    1179 
    1180     if (length < 1)
    1181         length = strlen (input);
    1182 
    1183     ret = tr_new0 (char, length);
    1184     b64 = BIO_new (BIO_f_base64 ());
    1185     bmem = BIO_new_mem_buf ((unsigned char*)input, length);
    1186     bmem = BIO_push (b64, bmem);
    1187     retlen = BIO_read (bmem, ret, length);
    1188     if (!retlen)
    1189     {
    1190         /* try again, but with the BIO_FLAGS_BASE64_NO_NL flag */
    1191         BIO_free_all (bmem);
    1192         b64 = BIO_new (BIO_f_base64 ());
    1193         BIO_set_flags (b64, BIO_FLAGS_BASE64_NO_NL);
    1194         bmem = BIO_new_mem_buf ((unsigned char*)input, length);
    1195         bmem = BIO_push (b64, bmem);
    1196         retlen = BIO_read (bmem, ret, length);
    1197     }
    1198 
    1199     if (setme_len)
    1200         *setme_len = retlen;
    1201 
    1202     BIO_free_all (bmem);
    1203     return ret;
     1185  char * ret;
     1186  BIO * b64;
     1187  BIO * bmem;
     1188  int retlen;
     1189
     1190  if (length < 1)
     1191    length = strlen (input);
     1192
     1193  ret = tr_new0 (char, length);
     1194  b64 = BIO_new (BIO_f_base64 ());
     1195  bmem = BIO_new_mem_buf ((unsigned char*)input, length);
     1196  bmem = BIO_push (b64, bmem);
     1197  retlen = BIO_read (bmem, ret, length);
     1198  if (!retlen)
     1199    {
     1200      /* try again, but with the BIO_FLAGS_BASE64_NO_NL flag */
     1201      BIO_free_all (bmem);
     1202      b64 = BIO_new (BIO_f_base64 ());
     1203      BIO_set_flags (b64, BIO_FLAGS_BASE64_NO_NL);
     1204      bmem = BIO_new_mem_buf ((unsigned char*)input, length);
     1205      bmem = BIO_push (b64, bmem);
     1206      retlen = BIO_read (bmem, ret, length);
     1207    }
     1208
     1209  if (setme_len)
     1210    *setme_len = retlen;
     1211
     1212  BIO_free_all (bmem);
     1213  return ret;
    12041214}
    12051215
     
    12141224                           size_t         nmemb)
    12151225{
    1216     char * a = array;
    1217 
    1218     memmove (a + sizeof_element * index_to_remove,
    1219              a + sizeof_element * (index_to_remove  + 1),
    1220              sizeof_element * (--nmemb - index_to_remove));
     1226  char * a = array;
     1227
     1228  memmove (a + sizeof_element * index_to_remove,
     1229           a + sizeof_element * (index_to_remove  + 1),
     1230           sizeof_element * (--nmemb - index_to_remove));
    12211231}
    12221232
     
    12291239               bool       * exact_match)
    12301240{
    1231     size_t first = 0;
    1232     const char * cbase = base;
    1233     bool exact = false;
    1234 
    1235     while (nmemb != 0)
    1236     {
    1237         const size_t half = nmemb / 2;
    1238         const size_t middle = first + half;
    1239         const int c = compar (key, cbase + size*middle);
    1240 
    1241         if (c <= 0) {
    1242             if (c == 0)
    1243                 exact = true;
    1244             nmemb = half;
    1245         } else {
    1246             first = middle + 1;
    1247             nmemb = nmemb - half - 1;
     1241  size_t first = 0;
     1242  const char * cbase = base;
     1243  bool exact = false;
     1244
     1245  while (nmemb != 0)
     1246    {
     1247      const size_t half = nmemb / 2;
     1248      const size_t middle = first + half;
     1249      const int c = compar (key, cbase + size*middle);
     1250
     1251      if (c <= 0)
     1252        {
     1253          if (c == 0)
     1254            exact = true;
     1255          nmemb = half;
    12481256        }
    1249     }
    1250 
    1251     *exact_match = exact;
    1252 
    1253     return first;
     1257      else
     1258        {
     1259          first = middle + 1;
     1260          nmemb = nmemb - half - 1;
     1261        }
     1262    }
     1263
     1264  *exact_match = exact;
     1265  return first;
    12541266}
    12551267
     
    13671379strip_non_utf8 (const char * in, size_t inlen)
    13681380{
    1369     const char * end;
    1370     const char zero = '\0';
    1371     struct evbuffer * buf = evbuffer_new ();
    1372 
    1373     while (!tr_utf8_validate (in, inlen, &end))
    1374     {
    1375         const int good_len = end - in;
    1376 
    1377         evbuffer_add (buf, in, good_len);
    1378         inlen -= (good_len + 1);
    1379         in += (good_len + 1);
    1380         evbuffer_add (buf, "?", 1);
    1381     }
    1382 
    1383     evbuffer_add (buf, in, inlen);
    1384     evbuffer_add (buf, &zero, 1);
    1385     return evbuffer_free_to_str (buf);
     1381  const char * end;
     1382  const char zero = '\0';
     1383  struct evbuffer * buf = evbuffer_new ();
     1384
     1385  while (!tr_utf8_validate (in, inlen, &end))
     1386    {
     1387      const int good_len = end - in;
     1388
     1389      evbuffer_add (buf, in, good_len);
     1390      inlen -= (good_len + 1);
     1391      in += (good_len + 1);
     1392      evbuffer_add (buf, "?", 1);
     1393    }
     1394
     1395  evbuffer_add (buf, in, inlen);
     1396  evbuffer_add (buf, &zero, 1);
     1397  return evbuffer_free_to_str (buf);
    13861398}
    13871399
     
    13891401to_utf8 (const char * in, size_t inlen)
    13901402{
    1391     char * ret = NULL;
     1403  char * ret = NULL;
    13921404
    13931405#ifdef HAVE_ICONV_OPEN
    1394     int i;
    1395     const char * encodings[] = { "CURRENT", "ISO-8859-15" };
    1396     const int encoding_count = sizeof (encodings) / sizeof (encodings[1]);
    1397     const size_t buflen = inlen*4 + 10;
    1398     char * out = tr_new (char, buflen);
    1399 
    1400     for (i=0; !ret && i<encoding_count; ++i)
    1401     {
    1402         char * inbuf = (char*) in;
    1403         char * outbuf = out;
    1404         size_t inbytesleft = inlen;
    1405         size_t outbytesleft = buflen;
    1406         const char * test_encoding = encodings[i];
    1407 
    1408         iconv_t cd = iconv_open ("UTF-8", test_encoding);
    1409         if (cd != (iconv_t)-1) {
    1410             if (iconv (cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft) != (size_t)-1)
    1411                 ret = tr_strndup (out, buflen-outbytesleft);
    1412             iconv_close (cd);
     1406  int i;
     1407  const char * encodings[] = { "CURRENT", "ISO-8859-15" };
     1408  const int encoding_count = sizeof (encodings) / sizeof (encodings[1]);
     1409  const size_t buflen = inlen*4 + 10;
     1410  char * out = tr_new (char, buflen);
     1411
     1412  for (i=0; !ret && i<encoding_count; ++i)
     1413    {
     1414      char * inbuf = (char*) in;
     1415      char * outbuf = out;
     1416      size_t inbytesleft = inlen;
     1417      size_t outbytesleft = buflen;
     1418      const char * test_encoding = encodings[i];
     1419
     1420      iconv_t cd = iconv_open ("UTF-8", test_encoding);
     1421      if (cd != (iconv_t)-1)
     1422        {
     1423          if (iconv (cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft) != (size_t)-1)
     1424            ret = tr_strndup (out, buflen-outbytesleft);
     1425          iconv_close (cd);
    14131426        }
    14141427    }
    14151428
    1416     tr_free (out);
    1417 #endif
    1418 
    1419     if (ret == NULL)
    1420         ret = strip_non_utf8 (in, inlen);
    1421 
    1422     return ret;
     1429  tr_free (out);
     1430#endif
     1431
     1432  if (ret == NULL)
     1433    ret = strip_non_utf8 (in, inlen);
     1434
     1435  return ret;
    14231436}
    14241437
     
    14261439tr_utf8clean (const char * str, int max_len)
    14271440{
    1428     char * ret;
    1429     const char * end;
    1430 
    1431     if (max_len < 0)
    1432         max_len = (int) strlen (str);
    1433 
    1434     if (tr_utf8_validate (str, max_len, &end))
    1435         ret = tr_strndup (str, max_len);
    1436     else
    1437         ret = to_utf8 (str, max_len);
    1438 
    1439     assert (tr_utf8_validate (ret, -1, NULL));
    1440     return ret;
     1441  char * ret;
     1442  const char * end;
     1443
     1444  if (max_len < 0)
     1445    max_len = (int) strlen (str);
     1446
     1447  if (tr_utf8_validate (str, max_len, &end))
     1448    ret = tr_strndup (str, max_len);
     1449  else
     1450    ret = to_utf8 (str, max_len);
     1451
     1452  assert (tr_utf8_validate (ret, -1, NULL));
     1453  return ret;
    14411454}
    14421455
     
    14471460struct number_range
    14481461{
    1449     int low;
    1450     int high;
     1462  int low;
     1463  int high;
    14511464};
    14521465
     
    14581471parseNumberSection (const char * str, int len, struct number_range * setme)
    14591472{
    1460     long a, b;
    1461     bool success;
    1462     char * end;
    1463     const int error = errno;
    1464     char * tmp = tr_strndup (str, len);
    1465 
    1466     errno = 0;
    1467     a = b = strtol (tmp, &end, 10);
    1468     if (errno || (end == tmp)) {
     1473  long a, b;
     1474  bool success;
     1475  char * end;
     1476  const int error = errno;
     1477  char * tmp = tr_strndup (str, len);
     1478
     1479  errno = 0;
     1480  a = b = strtol (tmp, &end, 10);
     1481  if (errno || (end == tmp))
     1482    {
     1483      success = false;
     1484    }
     1485  else if (*end != '-')
     1486    {
     1487      success = true;
     1488    }
     1489  else
     1490    {
     1491      const char * pch = end + 1;
     1492      b = strtol (pch, &end, 10);
     1493      if (errno || (pch == end))
    14691494        success = false;
    1470     } else if (*end != '-') {
     1495      else if (*end) /* trailing data */
     1496        success = false;
     1497      else
    14711498        success = true;
    1472     } else {
    1473         const char * pch = end + 1;
    1474         b = strtol (pch, &end, 10);
    1475         if (errno || (pch == end))
    1476             success = false;
    1477         else if (*end) /* trailing data */
    1478             success = false;
    1479         else
    1480             success = true;
    1481     }
    1482     tr_free (tmp);
    1483 
    1484     setme->low = MIN (a, b);
    1485     setme->high = MAX (a, b);
    1486 
    1487     errno = error;
    1488     return success;
     1499    }
     1500
     1501  tr_free (tmp);
     1502
     1503  setme->low = MIN (a, b);
     1504  setme->high = MAX (a, b);
     1505
     1506  errno = error;
     1507  return success;
    14891508}
    14901509
     
    14921511compareInt (const void * va, const void * vb)
    14931512{
    1494     const int a = * (const int *)va;
    1495     const int b = * (const int *)vb;
    1496     return a - b;
     1513  const int a = * (const int *)va;
     1514  const int b = * (const int *)vb;
     1515  return a - b;
    14971516}
    14981517
     
    15071526tr_parseNumberRange (const char * str_in, int len, int * setmeCount)
    15081527{
    1509     int n = 0;
    1510     int * uniq = NULL;
    1511     char * str = tr_strndup (str_in, len);
    1512     const char * walk;
    1513     tr_list * ranges = NULL;
    1514     bool success = true;
    1515 
    1516     walk = str;
    1517     while (walk && *walk && success) {
    1518         struct number_range range;
    1519         const char * pch = strchr (walk, ',');
    1520         if (pch) {
    1521             success = parseNumberSection (walk, pch-walk, &range);
    1522             walk = pch + 1;
    1523         } else {
    1524             success = parseNumberSection (walk, strlen (walk), &range);
    1525             walk += strlen (walk);
     1528  int n = 0;
     1529  int * uniq = NULL;
     1530  char * str = tr_strndup (str_in, len);
     1531  const char * walk;
     1532  tr_list * ranges = NULL;
     1533  bool success = true;
     1534
     1535  walk = str;
     1536  while (walk && *walk && success)
     1537    {
     1538      struct number_range range;
     1539      const char * pch = strchr (walk, ',');
     1540      if (pch)
     1541        {
     1542          success = parseNumberSection (walk, pch-walk, &range);
     1543          walk = pch + 1;
    15261544        }
    1527         if (success)
    1528             tr_list_append (&ranges, tr_memdup (&range, sizeof (struct number_range)));
    1529     }
    1530 
    1531     if (!success)
    1532     {
    1533         *setmeCount = 0;
    1534         uniq = NULL;
    1535     }
    1536     else
    1537     {
    1538         int i;
    1539         int n2;
    1540         tr_list * l;
    1541         int * sorted = NULL;
    1542 
    1543         /* build a sorted number array */
    1544         n = n2 = 0;
    1545         for (l=ranges; l!=NULL; l=l->next) {
    1546             const struct number_range * r = l->data;
    1547             n += r->high + 1 - r->low;
     1545      else
     1546        {
     1547          success = parseNumberSection (walk, strlen (walk), &range);
     1548          walk += strlen (walk);
    15481549        }
    1549         sorted = tr_new (int, n);
    1550         for (l=ranges; l!=NULL; l=l->next) {
    1551             const struct number_range * r = l->data;
    1552             int i;
    1553             for (i=r->low; i<=r->high; ++i)
    1554                 sorted[n2++] = i;
     1550      if (success)
     1551        tr_list_append (&ranges, tr_memdup (&range, sizeof (struct number_range)));
     1552    }
     1553
     1554  if (!success)
     1555    {
     1556      *setmeCount = 0;
     1557      uniq = NULL;
     1558    }
     1559  else
     1560    {
     1561      int i;
     1562      int n2;
     1563      tr_list * l;
     1564      int * sorted = NULL;
     1565
     1566      /* build a sorted number array */
     1567      n = n2 = 0;
     1568      for (l=ranges; l!=NULL; l=l->next)
     1569        {
     1570          const struct number_range * r = l->data;
     1571          n += r->high + 1 - r->low;
    15551572        }
    1556         qsort (sorted, n, sizeof (int), compareInt);
    1557         assert (n == n2);
    1558 
    1559         /* remove duplicates */
    1560         uniq = tr_new (int, n);
    1561         for (i=n=0; i<n2; ++i)
    1562             if (!n || uniq[n-1] != sorted[i])
    1563                 uniq[n++] = sorted[i];
    1564 
    1565         tr_free (sorted);
    1566     }
    1567 
    1568     /* cleanup */
    1569     tr_list_free (&ranges, tr_free);
    1570     tr_free (str);
    1571 
    1572     /* return the result */
    1573     *setmeCount = n;
    1574     return uniq;
     1573      sorted = tr_new (int, n);
     1574      for (l=ranges; l!=NULL; l=l->next)
     1575        {
     1576          int i;
     1577          const struct number_range * r = l->data;
     1578          for (i=r->low; i<=r->high; ++i)
     1579            sorted[n2++] = i;
     1580        }
     1581      qsort (sorted, n, sizeof (int), compareInt);
     1582      assert (n == n2);
     1583
     1584      /* remove duplicates */
     1585      uniq = tr_new (int, n);
     1586      for (i=n=0; i<n2; ++i)
     1587        if (!n || uniq[n-1] != sorted[i])
     1588          uniq[n++] = sorted[i];
     1589
     1590      tr_free (sorted);
     1591    }
     1592
     1593  /* cleanup */
     1594  tr_list_free (&ranges, tr_free);
     1595  tr_free (str);
     1596
     1597  /* return the result */
     1598  *setmeCount = n;
     1599  return uniq;
    15751600}
    15761601
     
    15821607tr_truncd (double x, int precision)
    15831608{
    1584     char * pt;
    1585     char buf[128];
    1586     const int max_precision = (int) log10 (1.0 / DBL_EPSILON) - 1;
    1587     tr_snprintf (buf, sizeof (buf), "%.*f", max_precision, x);
    1588     if ((pt = strstr (buf, localeconv ()->decimal_point)))
    1589         pt[precision ? precision+1 : 0] = '\0';
    1590     return atof (buf);
     1609  char * pt;
     1610  char buf[128];
     1611  const int max_precision = (int) log10 (1.0 / DBL_EPSILON) - 1;
     1612  tr_snprintf (buf, sizeof (buf), "%.*f", max_precision, x);
     1613  if ((pt = strstr (buf, localeconv ()->decimal_point)))
     1614    pt[precision ? precision+1 : 0] = '\0';
     1615  return atof (buf);
    15911616}
    15921617
     
    15951620tr_strtruncd (char * buf, double x, int precision, size_t buflen)
    15961621{
    1597     tr_snprintf (buf, buflen, "%.*f", precision, tr_truncd (x, precision));
    1598     return buf;
     1622  tr_snprintf (buf, buflen, "%.*f", precision, tr_truncd (x, precision));
     1623  return buf;
    15991624}
    16001625
     
    16021627tr_strpercent (char * buf, double x, size_t buflen)
    16031628{
    1604     if (x < 10.0)
    1605         tr_strtruncd (buf, x, 2, buflen);
    1606     else if (x < 100.0)
    1607         tr_strtruncd (buf, x, 1, buflen);
    1608     else
    1609         tr_strtruncd (buf, x, 0, buflen);
    1610     return buf;
     1629  if (x < 10.0)
     1630    tr_strtruncd (buf, x, 2, buflen);
     1631  else if (x < 100.0)
     1632    tr_strtruncd (buf, x, 1, buflen);
     1633  else
     1634    tr_strtruncd (buf, x, 0, buflen);
     1635
     1636  return buf;
    16111637}
    16121638
     
    16141640tr_strratio (char * buf, size_t buflen, double ratio, const char * infinity)
    16151641{
    1616     if ((int)ratio == TR_RATIO_NA)
    1617         tr_strlcpy (buf, _("None"), buflen);
    1618     else if ((int)ratio == TR_RATIO_INF)
    1619         tr_strlcpy (buf, infinity, buflen);
    1620     else
    1621         tr_strpercent (buf, ratio, buflen);
    1622     return buf;
     1642  if ((int)ratio == TR_RATIO_NA)
     1643    tr_strlcpy (buf, _("None"), buflen);
     1644  else if ((int)ratio == TR_RATIO_INF)
     1645    tr_strlcpy (buf, infinity, buflen);
     1646  else
     1647    tr_strpercent (buf, ratio, buflen);
     1648
     1649  return buf;
    16231650}
    16241651
     
    16301657tr_moveFile (const char * oldpath, const char * newpath, bool * renamed)
    16311658{
    1632     int in;
    1633     int out;
    1634     char * buf;
    1635     struct stat st;
    1636     off_t bytesLeft;
    1637     const size_t buflen = 1024 * 128; /* 128 KiB buffer */
    1638 
    1639     /* make sure the old file exists */
    1640     if (stat (oldpath, &st)) {
    1641         const int err = errno;
    1642         errno = err;
    1643         return -1;
    1644     }
    1645     if (!S_ISREG (st.st_mode)) {
    1646         errno = ENOENT;
    1647         return -1;
    1648     }
    1649     bytesLeft = st.st_size;
    1650 
    1651     /* make sure the target directory exists */
    1652     {
    1653         char * newdir = tr_dirname (newpath);
    1654         int i = tr_mkdirp (newdir, 0777);
    1655         tr_free (newdir);
    1656         if (i)
    1657             return i;
    1658     }
    1659 
    1660     /* they might be on the same filesystem... */
    1661     {
    1662         const int i = rename (oldpath, newpath);
    1663         if (renamed != NULL)
    1664             *renamed = i == 0;
    1665         if (!i)
    1666             return 0;
    1667     }
    1668 
    1669     /* copy the file */
    1670     in = tr_open_file_for_scanning (oldpath);
    1671     out = tr_open_file_for_writing (newpath);
    1672     buf = tr_valloc (buflen);
    1673     while (bytesLeft > 0)
    1674     {
    1675         ssize_t bytesWritten;
    1676         const off_t bytesThisPass = MIN (bytesLeft, (off_t)buflen);
    1677         const int numRead = read (in, buf, bytesThisPass);
    1678         if (numRead < 0)
    1679             break;
    1680         bytesWritten = write (out, buf, numRead);
    1681         if (bytesWritten < 0)
    1682             break;
    1683         bytesLeft -= bytesWritten;
    1684     }
    1685 
    1686     /* cleanup */
    1687     tr_free (buf);
    1688     tr_close_file (out);
    1689     tr_close_file (in);
    1690     if (bytesLeft != 0)
    1691         return -1;
    1692 
    1693     unlink (oldpath);
    1694     return 0;
     1659  int in;
     1660  int out;
     1661  char * buf;
     1662  struct stat st;
     1663  off_t bytesLeft;
     1664  const size_t buflen = 1024 * 128; /* 128 KiB buffer */
     1665
     1666  /* make sure the old file exists */
     1667  if (stat (oldpath, &st))
     1668    {
     1669      const int err = errno;
     1670      errno = err;
     1671      return -1;
     1672    }
     1673  if (!S_ISREG (st.st_mode))
     1674    {
     1675      errno = ENOENT;
     1676      return -1;
     1677    }
     1678  bytesLeft = st.st_size;
     1679
     1680  /* make sure the target directory exists */
     1681  {
     1682    char * newdir = tr_dirname (newpath);
     1683    int i = tr_mkdirp (newdir, 0777);
     1684    tr_free (newdir);
     1685    if (i)
     1686      return i;
     1687  }
     1688
     1689  /* they might be on the same filesystem... */
     1690  {
     1691    const int i = rename (oldpath, newpath);
     1692    if (renamed != NULL)
     1693      *renamed = i == 0;
     1694    if (!i)
     1695      return 0;
     1696  }
     1697
     1698  /* copy the file */
     1699  in = tr_open_file_for_scanning (oldpath);
     1700  out = tr_open_file_for_writing (newpath);
     1701  buf = tr_valloc (buflen);
     1702  while (bytesLeft > 0)
     1703    {
     1704      ssize_t bytesWritten;
     1705      const off_t bytesThisPass = MIN (bytesLeft, (off_t)buflen);
     1706      const int numRead = read (in, buf, bytesThisPass);
     1707      if (numRead < 0)
     1708        break;
     1709      bytesWritten = write (out, buf, numRead);
     1710      if (bytesWritten < 0)
     1711        break;
     1712      bytesLeft -= bytesWritten;
     1713    }
     1714
     1715  /* cleanup */
     1716  tr_free (buf);
     1717  tr_close_file (out);
     1718  tr_close_file (in);
     1719  if (bytesLeft != 0)
     1720    return -1;
     1721
     1722  unlink (oldpath);
     1723  return 0;
    16951724}
    16961725
     
    16981727tr_is_same_file (const char * filename1, const char * filename2)
    16991728{
    1700     struct stat sb1, sb2;
    1701 
    1702     return !stat (filename1, &sb1)
    1703         && !stat (filename2, &sb2)
    1704         && (sb1.st_dev == sb2.st_dev)
    1705         && (sb1.st_ino == sb2.st_ino);
     1729  struct stat sb1, sb2;
     1730
     1731  return !stat (filename1, &sb1)
     1732      && !stat (filename2, &sb2)
     1733      && (sb1.st_dev == sb2.st_dev)
     1734      && (sb1.st_ino == sb2.st_ino);
    17061735}
    17071736
     
    17131742tr_valloc (size_t bufLen)
    17141743{
    1715     size_t allocLen;
    1716     void * buf = NULL;
    1717     static size_t pageSize = 0;
    1718 
    1719     if (!pageSize) {
     1744  size_t allocLen;
     1745  void * buf = NULL;
     1746  static size_t pageSize = 0;
     1747
     1748  if (!pageSize)
     1749    {
    17201750#ifdef HAVE_GETPAGESIZE
    1721         pageSize = (size_t) getpagesize ();
     1751      pageSize = (size_t) getpagesize ();
    17221752#else /* guess */
    1723         pageSize = 4096;
    1724 #endif
    1725     }
    1726 
    1727     allocLen = pageSize;
    1728     while (allocLen < bufLen)
    1729         allocLen += pageSize;
     1753      pageSize = 4096;
     1754#endif
     1755    }
     1756
     1757  allocLen = pageSize;
     1758  while (allocLen < bufLen)
     1759    allocLen += pageSize;
    17301760
    17311761#ifdef HAVE_POSIX_MEMALIGN
    1732     if (!buf)
    1733         if (posix_memalign (&buf, pageSize, allocLen))
    1734             buf = NULL; /* just retry with valloc/malloc */
     1762  if (!buf)
     1763    if (posix_memalign (&buf, pageSize, allocLen))
     1764      buf = NULL; /* just retry with valloc/malloc */
    17351765#endif
    17361766#ifdef HAVE_VALLOC
    1737     if (!buf)
    1738         buf = valloc (allocLen);
    1739 #endif
    1740     if (!buf)
    1741         buf = tr_malloc (allocLen);
    1742 
    1743     return buf;
     1767  if (!buf)
     1768    buf = valloc (allocLen);
     1769#endif
     1770  if (!buf)
     1771    buf = tr_malloc (allocLen);
     1772
     1773  return buf;
    17441774}
    17451775
     
    17481778{
    17491779#ifdef WIN32
    1750     /* From a message to the Mingw-msys list, Jun 2, 2005 by Mark Junker. */
    1751     if (GetFullPathNameA (path, TR_PATH_MAX, resolved_path, NULL) == 0)
    1752         return NULL;
    1753     return resolved_path;
     1780  /* From a message to the Mingw-msys list, Jun 2, 2005 by Mark Junker. */
     1781  if (GetFullPathNameA (path, TR_PATH_MAX, resolved_path, NULL) == 0)
     1782    return NULL;
     1783  return resolved_path;
    17541784#else
    1755     return realpath (path, resolved_path);
     1785  return realpath (path, resolved_path);
    17561786#endif
    17571787}
     
    17651795{
    17661796#ifdef HAVE_HTONLL
    1767     return htonll (x);
     1797  return htonll (x);
    17681798#else
    1769     /* fallback code by bdonlan at
    1770      * http://stackoverflow.com/questions/809902/64-bit-ntohl-in-c/875505#875505 */
    1771     union { uint32_t lx[2]; uint64_t llx; } u;
    1772     u.lx[0] = htonl (x >> 32);
    1773     u.lx[1] = htonl (x & 0xFFFFFFFFULL);
    1774     return u.llx;
     1799  /* fallback code by bdonlan at
     1800   * http://stackoverflow.com/questions/809902/64-bit-ntohl-in-c/875505#875505 */
     1801  union { uint32_t lx[2]; uint64_t llx; } u;
     1802  u.lx[0] = htonl (x >> 32);
     1803  u.lx[1] = htonl (x & 0xFFFFFFFFULL);
     1804  return u.llx;
    17751805#endif
    17761806}
     
    17801810{
    17811811#ifdef HAVE_NTOHLL
    1782     return ntohll (x);
     1812  return ntohll (x);
    17831813#else
    1784     /* fallback code by bdonlan at
    1785      * http://stackoverflow.com/questions/809902/64-bit-ntohl-in-c/875505#875505 */
    1786     union { uint32_t lx[2]; uint64_t llx; } u;
    1787     u.llx = x;
    1788     return ((uint64_t)ntohl (u.lx[0]) << 32) | (uint64_t)ntohl (u.lx[1]);
     1814  /* fallback code by bdonlan at
     1815   * http://stackoverflow.com/questions/809902/64-bit-ntohl-in-c/875505#875505 */
     1816  union { uint32_t lx[2]; uint64_t llx; } u;
     1817  u.llx = x;
     1818  return ((uint64_t)ntohl (u.lx[0]) << 32) | (uint64_t)ntohl (u.lx[1]);
    17891819#endif
    17901820}
     
    17981828struct formatter_unit
    17991829{
    1800     char * name;
    1801     int64_t value;
     1830  char * name;
     1831  int64_t value;
    18021832};
    18031833
    18041834struct formatter_units
    18051835{
    1806     struct formatter_unit units[4];
     1836  struct formatter_unit units[4];
    18071837};
    18081838
     
    18151845                const char * gb, const char * tb)
    18161846{
    1817     uint64_t value = kilo;
    1818     units->units[TR_FMT_KB].name = tr_strdup (kb);
    1819     units->units[TR_FMT_KB].value = value;
    1820 
    1821     value *= kilo;
    1822     units->units[TR_FMT_MB].name = tr_strdup (mb);
    1823     units->units[TR_FMT_MB].value = value;
    1824 
    1825     value *= kilo;
    1826     units->units[TR_FMT_GB].name = tr_strdup (gb);
    1827     units->units[TR_FMT_GB].value = value;
    1828 
    1829     value *= kilo;
    1830     units->units[TR_FMT_TB].name = tr_strdup (tb);
    1831     units->units[TR_FMT_TB].value = value;
     1847  uint64_t value;
     1848
     1849  value = kilo;
     1850  units->units[TR_FMT_KB].name = tr_strdup (kb);
     1851  units->units[TR_FMT_KB].value = value;
     1852
     1853  value *= kilo;
     1854  units->units[TR_FMT_MB].name = tr_strdup (mb);
     1855  units->units[TR_FMT_MB].value = value;
     1856
     1857  value *= kilo;
     1858  units->units[TR_FMT_GB].name = tr_strdup (gb);
     1859  units->units[TR_FMT_GB].value = value;
     1860
     1861  value *= kilo;
     1862  units->units[TR_FMT_TB].name = tr_strdup (tb);
     1863  units->units[TR_FMT_TB].value = value;
    18321864}
    18331865
     
    18361868                        char * buf, int64_t bytes, size_t buflen)
    18371869{
    1838     int precision;
    1839     double value;
    1840     const char * units;
    1841     const struct formatter_unit * unit;
    1842 
    1843          if (bytes < u->units[1].value) unit = &u->units[0];
    1844     else if (bytes < u->units[2].value) unit = &u->units[1];
    1845     else if (bytes < u->units[3].value) unit = &u->units[2];
    1846     else                                 unit = &u->units[3];
    1847 
    1848     value = (double)bytes / unit->value;
    1849     units = unit->name;
    1850     if (unit->value == 1)
    1851         precision = 0;
    1852     else if (value < 100)
    1853         precision = 2;
    1854     else
    1855         precision = 1;
    1856     tr_snprintf (buf, buflen, "%.*f %s", precision, value, units);
    1857     return buf;
     1870  int precision;
     1871  double value;
     1872  const char * units;
     1873  const struct formatter_unit * unit;
     1874
     1875       if (bytes < u->units[1].value) unit = &u->units[0];
     1876  else if (bytes < u->units[2].value) unit = &u->units[1];
     1877  else if (bytes < u->units[3].value) unit = &u->units[2];
     1878  else                                unit = &u->units[3];
     1879
     1880  value = (double)bytes / unit->value;
     1881  units = unit->name;
     1882
     1883  if (unit->value == 1)
     1884    precision = 0;
     1885  else if (value < 100)
     1886    precision = 2;
     1887  else
     1888    precision = 1;
     1889
     1890  tr_snprintf (buf, buflen, "%.*f %s", precision, value, units);
     1891  return buf;
    18581892}
    18591893
     
    18651899                        const char * gb, const char * tb)
    18661900{
    1867     formatter_init (&size_units, kilo, kb, mb, gb, tb);
     1901  formatter_init (&size_units, kilo, kb, mb, gb, tb);
    18681902}
    18691903
     
    18711905tr_formatter_size_B (char * buf, int64_t bytes, size_t buflen)
    18721906{
    1873     return formatter_get_size_str (&size_units, buf, bytes, buflen);
     1907  return formatter_get_size_str (&size_units, buf, bytes, buflen);
    18741908}
    18751909
     
    18831917                         const char * gb, const char * tb)
    18841918{
    1885     tr_speed_K = kilo;
    1886     formatter_init (&speed_units, kilo, kb, mb, gb, tb);
     1919  tr_speed_K = kilo;
     1920  formatter_init (&speed_units, kilo, kb, mb, gb, tb);
    18871921}
    18881922
     
    18901924tr_formatter_speed_KBps (char * buf, double KBps, size_t buflen)
    18911925{
    1892     const double K = speed_units.units[TR_FMT_KB].value;
    1893     double speed = KBps;
    1894 
    1895     if (speed <= 999.95) /* 0.0 KB to 999.9 KB */
    1896         tr_snprintf (buf, buflen, "%d %s", (int)speed, speed_units.units[TR_FMT_KB].name);
    1897     else {
    1898         speed /= K;
    1899         if (speed <= 99.995) /* 0.98 MB to 99.99 MB */
    1900             tr_snprintf (buf, buflen, "%.2f %s", speed, speed_units.units[TR_FMT_MB].name);
    1901         else if (speed <= 999.95) /* 100.0 MB to 999.9 MB */
    1902             tr_snprintf (buf, buflen, "%.1f %s", speed, speed_units.units[TR_FMT_MB].name);
    1903         else {
    1904             speed /= K;
    1905             tr_snprintf (buf, buflen, "%.1f %s", speed, speed_units.units[TR_FMT_GB].name);
    1906         }
    1907     }
    1908 
    1909     return buf;
     1926  const double K = speed_units.units[TR_FMT_KB].value;
     1927  double speed = KBps;
     1928
     1929  if (speed <= 999.95) /* 0.0 KB to 999.9 KB */
     1930    {
     1931      tr_snprintf (buf, buflen, "%d %s", (int)speed, speed_units.units[TR_FMT_KB].name);
     1932    }
     1933  else
     1934    {
     1935      speed /= K;
     1936
     1937      if (speed <= 99.995) /* 0.98 MB to 99.99 MB */
     1938        tr_snprintf (buf, buflen, "%.2f %s", speed, speed_units.units[TR_FMT_MB].name);
     1939      else if (speed <= 999.95) /* 100.0 MB to 999.9 MB */
     1940        tr_snprintf (buf, buflen, "%.1f %s", speed, speed_units.units[TR_FMT_MB].name);
     1941      else
     1942        tr_snprintf (buf, buflen, "%.1f %s", speed/K, speed_units.units[TR_FMT_GB].name);
     1943    }
     1944
     1945  return buf;
    19101946}
    19111947
     
    19191955                       const char * gb, const char * tb)
    19201956{
    1921     tr_mem_K = kilo;
    1922     formatter_init (&mem_units, kilo, kb, mb, gb, tb);
     1957  tr_mem_K = kilo;
     1958  formatter_init (&mem_units, kilo, kb, mb, gb, tb);
    19231959}
    19241960
     
    19261962tr_formatter_mem_B (char * buf, int64_t bytes_per_second, size_t buflen)
    19271963{
    1928     return formatter_get_size_str (&mem_units, buf, bytes_per_second, buflen);
     1964  return formatter_get_size_str (&mem_units, buf, bytes_per_second, buflen);
    19291965}
    19301966
  • trunk/libtransmission/web.c

    r13625 r13863  
    3939enum
    4040{
    41     THREADFUNC_MAX_SLEEP_MSEC = 1000,
     41  THREADFUNC_MAX_SLEEP_MSEC = 1000,
    4242};
    4343
    4444#if 0
    4545#define dbgmsg(...) \
    46     do { \
    47         fprintf (stderr, __VA_ARGS__); \
    48         fprintf (stderr, "\n"); \
    49     } while (0)
     46  do { \
     47    fprintf (stderr, __VA_ARGS__); \
     48    fprintf (stderr, "\n"); \
     49  } while (0)
    5050#else
    5151#define dbgmsg(...) \
    52     do { \
    53         if (tr_deepLoggingIsActive ()) \
    54             tr_deepLog (__FILE__, __LINE__, "web", __VA_ARGS__); \
    55     } while (0)
     52  do { \
     53    if (tr_deepLoggingIsActive ()) \
     54      tr_deepLog (__FILE__, __LINE__, "web", __VA_ARGS__); \
     55  } while (0)
    5656#endif
    5757
     
    6262struct tr_web_task
    6363{
    64     long code;
    65     long timeout_secs;
    66     bool did_connect;
    67     bool did_timeout;
    68     struct evbuffer * response;
    69     struct evbuffer * freebuf;
    70     char * url;
    71     char * range;
    72     char * cookies;
    73     tr_session * session;
    74     tr_web_done_func * done_func;
    75     void * done_func_user_data;
    76     CURL * curl_easy;
    77     struct tr_web_task * next;
     64  long code;
     65  long timeout_secs;
     66  bool did_connect;
     67  bool did_timeout;
     68  struct evbuffer * response;
     69  struct evbuffer * freebuf;
     70  char * url;
     71  char * range;
     72  char * cookies;
     73  tr_session * session;
     74  tr_web_done_func * done_func;
     75  void * done_func_user_data;
     76  CURL * curl_easy;
     77  struct tr_web_task * next;
    7878};
    7979
     
    8181task_free (struct tr_web_task * task)
    8282{
    83     if (task->freebuf)
    84         evbuffer_free (task->freebuf);
    85     tr_free (task->cookies);
    86     tr_free (task->range);
    87     tr_free (task->url);
    88     tr_free (task);
     83  if (task->freebuf)
     84    evbuffer_free (task->freebuf);
     85  tr_free (task->cookies);
     86  tr_free (task->range);
     87  tr_free (task->url);
     88  tr_free (task);
    8989}
    9090
     
    9595struct tr_web
    9696{
    97     bool curl_verbose;
    98     bool curl_ssl_verify;
    99     const char * curl_ca_bundle;
    100     int close_mode;
    101     struct tr_web_task * tasks;
    102     tr_lock * taskLock;
    103     char * cookie_filename;
     97  bool curl_verbose;
     98  bool curl_ssl_verify;
     99  const char * curl_ca_bundle;
     100  int close_mode;
     101  struct tr_web_task * tasks;
     102  tr_lock * taskLock;
     103  char * cookie_filename;
    104104};
    105105
     
    111111writeFunc (void * ptr, size_t size, size_t nmemb, void * vtask)
    112112{
    113     const size_t byteCount = size * nmemb;
    114     struct tr_web_task * task = vtask;
    115     evbuffer_add (task->response, ptr, byteCount);
    116     dbgmsg ("wrote %zu bytes to task %p's buffer", byteCount, task);
    117     return byteCount;
     113  const size_t byteCount = size * nmemb;
     114  struct tr_web_task * task = vtask;
     115  evbuffer_add (task->response, ptr, byteCount);
     116  dbgmsg ("wrote %zu bytes to task %p's buffer", byteCount, task);
     117  return byteCount;
    118118}
    119119
     
    122122sockoptfunction (void * vtask, curl_socket_t fd, curlsocktype purpose UNUSED)
    123123{
    124     struct tr_web_task * task = vtask;
    125     const bool isScrape = strstr (task->url, "scrape") != NULL;
    126     const bool isAnnounce = strstr (task->url, "announce") != NULL;
    127 
    128     /* announce and scrape requests have tiny payloads. */
    129     if (isScrape || isAnnounce)
    130     {
    131         const int sndbuf = 1024;
    132         const int rcvbuf = isScrape ? 2048 : 3072;
    133         setsockopt (fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof (sndbuf));
    134         setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof (rcvbuf));
    135     }
    136 
    137     /* return nonzero if this function encountered an error */
    138     return 0;
     124  struct tr_web_task * task = vtask;
     125  const bool isScrape = strstr (task->url, "scrape") != NULL;
     126  const bool isAnnounce = strstr (task->url, "announce") != NULL;
     127
     128  /* announce and scrape requests have tiny payloads. */
     129  if (isScrape || isAnnounce)
     130    {
     131      const int sndbuf = 1024;
     132      const int rcvbuf = isScrape ? 2048 : 3072;
     133      setsockopt (fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof (sndbuf));
     134      setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof (rcvbuf));
     135    }
     136
     137  /* return nonzero if this function encountered an error */
     138  return 0;
    139139}
    140140#endif
     
    143143getTimeoutFromURL (const struct tr_web_task * task)
    144144{
    145     long timeout;
    146     const tr_session * session = task->session;
    147 
    148     if (!session || session->isClosed) timeout = 20L;
    149     else if (strstr (task->url, "scrape") != NULL) timeout = 30L;
    150     else if (strstr (task->url, "announce") != NULL) timeout = 90L;
    151     else timeout = 240L;
    152 
    153     return timeout;
     145  long timeout;
     146  const tr_session * session = task->session;
     147
     148  if (!session || session->isClosed) timeout = 20L;
     149  else if (strstr (task->url, "scrape") != NULL) timeout = 30L;
     150  else if (strstr (task->url, "announce") != NULL) timeout = 90L;
     151  else timeout = 240L;
     152
     153  return timeout;
    154154}
    155155
     
    157157createEasy (tr_session * s, struct tr_web * web, struct tr_web_task * task)
    158158{
    159     bool is_default_value;
    160     const tr_address * addr;
    161     CURL * e = task->curl_easy = curl_easy_init ();
    162 
    163     task->timeout_secs = getTimeoutFromURL (task);
    164 
    165     curl_easy_setopt (e, CURLOPT_AUTOREFERER, 1L);
    166     curl_easy_setopt (e, CURLOPT_COOKIEFILE, web->cookie_filename);
    167     curl_easy_setopt (e, CURLOPT_ENCODING, "gzip;q=1.0, deflate, identity");
    168     curl_easy_setopt (e, CURLOPT_FOLLOWLOCATION, 1L);
    169     curl_easy_setopt (e, CURLOPT_MAXREDIRS, -1L);
    170     curl_easy_setopt (e, CURLOPT_NOSIGNAL, 1L);
    171     curl_easy_setopt (e, CURLOPT_PRIVATE, task);
     159  bool is_default_value;
     160  const tr_address * addr;
     161  CURL * e = task->curl_easy = curl_easy_init ();
     162
     163  task->timeout_secs = getTimeoutFromURL (task);
     164
     165  curl_easy_setopt (e, CURLOPT_AUTOREFERER, 1L);
     166  curl_easy_setopt (e, CURLOPT_COOKIEFILE, web->cookie_filename);
     167  curl_easy_setopt (e, CURLOPT_ENCODING, "gzip;q=1.0, deflate, identity");
     168  curl_easy_setopt (e, CURLOPT_FOLLOWLOCATION, 1L);
     169  curl_easy_setopt (e, CURLOPT_MAXREDIRS, -1L);
     170  curl_easy_setopt (e, CURLOPT_NOSIGNAL, 1L);
     171  curl_easy_setopt (e, CURLOPT_PRIVATE, task);
    172172#ifdef USE_LIBCURL_SOCKOPT
    173     curl_easy_setopt (e, CURLOPT_SOCKOPTFUNCTION, sockoptfunction);
    174     curl_easy_setopt (e, CURLOPT_SOCKOPTDATA, task);
     173  curl_easy_setopt (e, CURLOPT_SOCKOPTFUNCTION, sockoptfunction);
     174  curl_easy_setopt (e, CURLOPT_SOCKOPTDATA, task);
    175175#endif
    176     if (web->curl_ssl_verify)
    177         curl_easy_setopt (e, CURLOPT_CAINFO, web->curl_ca_bundle);
    178     else {
    179         curl_easy_setopt (e, CURLOPT_SSL_VERIFYHOST, 0L);
    180         curl_easy_setopt (e, CURLOPT_SSL_VERIFYPEER, 0L);
    181     }
    182     curl_easy_setopt (e, CURLOPT_TIMEOUT, task->timeout_secs);
    183     curl_easy_setopt (e, CURLOPT_URL, task->url);
    184     curl_easy_setopt (e, CURLOPT_USERAGENT, TR_NAME "/" SHORT_VERSION_STRING);
    185     curl_easy_setopt (e, CURLOPT_VERBOSE, (long)(web->curl_verbose?1:0));
    186     curl_easy_setopt (e, CURLOPT_WRITEDATA, task);
    187     curl_easy_setopt (e, CURLOPT_WRITEFUNCTION, writeFunc);
    188 
    189     if (((addr = tr_sessionGetPublicAddress (s, TR_AF_INET, &is_default_value))) && !is_default_value)
    190         curl_easy_setopt (e, CURLOPT_INTERFACE, tr_address_to_string (addr));
    191     else if (((addr = tr_sessionGetPublicAddress (s, TR_AF_INET6, &is_default_value))) && !is_default_value)
    192         curl_easy_setopt (e, CURLOPT_INTERFACE, tr_address_to_string (addr));
    193 
    194     if (task->cookies != NULL)
    195         curl_easy_setopt (e, CURLOPT_COOKIE, task->cookies);
    196 
    197     if (task->range != NULL) {
    198         curl_easy_setopt (e, CURLOPT_RANGE, task->range);
    199         /* don't bother asking the server to compress webseed fragments */
    200         curl_easy_setopt (e, CURLOPT_ENCODING, "identity");
    201     }
    202 
    203     return e;
     176  if (web->curl_ssl_verify)
     177    {
     178      curl_easy_setopt (e, CURLOPT_CAINFO, web->curl_ca_bundle);
     179    }
     180  else
     181    {
     182      curl_easy_setopt (e, CURLOPT_SSL_VERIFYHOST, 0L);
     183      curl_easy_setopt (e, CURLOPT_SSL_VERIFYPEER, 0L);
     184    }
     185  curl_easy_setopt (e, CURLOPT_TIMEOUT, task->timeout_secs);
     186  curl_easy_setopt (e, CURLOPT_URL, task->url);
     187  curl_easy_setopt (e, CURLOPT_USERAGENT, TR_NAME "/" SHORT_VERSION_STRING);
     188  curl_easy_setopt (e, CURLOPT_VERBOSE, (long)(web->curl_verbose?1:0));
     189  curl_easy_setopt (e, CURLOPT_WRITEDATA, task);
     190  curl_easy_setopt (e, CURLOPT_WRITEFUNCTION, writeFunc);
     191
     192  if (((addr = tr_sessionGetPublicAddress (s, TR_AF_INET, &is_default_value))) && !is_default_value)
     193    curl_easy_setopt (e, CURLOPT_INTERFACE, tr_address_to_string (addr));
     194  else if (((addr = tr_sessionGetPublicAddress (s, TR_AF_INET6, &is_default_value))) && !is_default_value)
     195    curl_easy_setopt (e, CURLOPT_INTERFACE, tr_address_to_string (addr));
     196
     197  if (task->cookies != NULL)
     198    curl_easy_setopt (e, CURLOPT_COOKIE, task->cookies);
     199
     200  if (task->range != NULL)
     201    {
     202      curl_easy_setopt (e, CURLOPT_RANGE, task->range);
     203      /* don't bother asking the server to compress webseed fragments */
     204      curl_easy_setopt (e, CURLOPT_ENCODING, "identity");
     205    }
     206
     207  return e;
    204208}
    205209
     
    211215task_finish_func (void * vtask)
    212216{
    213     struct tr_web_task * task = vtask;
    214     dbgmsg ("finished web task %p; got %ld", task, task->code);
    215 
    216     if (task->done_func != NULL)
    217         task->done_func (task->session,
    218                          task->did_connect,
    219                          task->did_timeout,
    220                          task->code,
    221                          evbuffer_pullup (task->response, -1),
    222                          evbuffer_get_length (task->response),
    223                          task->done_func_user_data);
    224 
    225     task_free (task);
     217  struct tr_web_task * task = vtask;
     218  dbgmsg ("finished web task %p; got %ld", task, task->code);
     219
     220  if (task->done_func != NULL)
     221    task->done_func (task->session,
     222                     task->did_connect,
     223                     task->did_timeout,
     224                     task->code,
     225                     evbuffer_pullup (task->response, -1),
     226                     evbuffer_get_length (task->response),
     227                     task->done_func_user_data);
     228
     229  task_free (task);
    226230}
    227231
     
    238242           void               * done_func_user_data)
    239243{
    240     return tr_webRunWithBuffer (session, url, range, cookies,
    241                                 done_func, done_func_user_data,
    242                                 NULL);
     244  return tr_webRunWithBuffer (session, url, range, cookies,
     245                              done_func, done_func_user_data,
     246                              NULL);
    243247}
    244248
     
    252256                     struct evbuffer    * buffer)
    253257{
    254     struct tr_web * web = session->web;
    255 
    256     if (web != NULL)
    257     {
    258         struct tr_web_task * task = tr_new0 (struct tr_web_task, 1);
    259 
    260         task->session = session;
    261         task->url = tr_strdup (url);
    262         task->range = tr_strdup (range);
    263         task->cookies = tr_strdup (cookies);
    264         task->done_func = done_func;
    265         task->done_func_user_data = done_func_user_data;
    266         task->response = buffer ? buffer : evbuffer_new ();
    267         task->freebuf = buffer ? NULL : task->response;
    268 
    269         tr_lockLock (web->taskLock);
    270         task->next = web->tasks;
    271         web->tasks = task;
    272         tr_lockUnlock (web->taskLock);
    273         return task;
    274     }
    275     return NULL;
     258  struct tr_web * web = session->web;
     259
     260  if (web != NULL)
     261    {
     262      struct tr_web_task * task = tr_new0 (struct tr_web_task, 1);
     263
     264      task->session = session;
     265      task->url = tr_strdup (url);
     266      task->range = tr_strdup (range);
     267      task->cookies = tr_strdup (cookies);
     268      task->done_func = done_func;
     269      task->done_func_user_data = done_func_user_data;
     270      task->response = buffer ? buffer : evbuffer_new ();
     271      task->freebuf = buffer ? NULL : task->response;
     272
     273      tr_lockLock (web->taskLock);
     274      task->next = web->tasks;
     275      web->tasks = task;
     276      tr_lockUnlock (web->taskLock);
     277      return task;
     278    }
     279
     280  return NULL;
    276281}
    277282
     
    290295{
    291296#ifdef WIN32
    292     if (!r_fd_set->fd_count && !w_fd_set->fd_count && !c_fd_set->fd_count)
    293     {
    294         const long int msec = t->tv_sec*1000 + t->tv_usec/1000;
    295         tr_wait_msec (msec);
    296     }
    297     else if (select (0, r_fd_set->fd_count ? r_fd_set : NULL,
    298                         w_fd_set->fd_count ? w_fd_set : NULL,
    299                         c_fd_set->fd_count ? c_fd_set : NULL, t) < 0)
    300     {
    301         char errstr[512];
    302         const int e = EVUTIL_SOCKET_ERROR ();
    303         tr_net_strerror (errstr, sizeof (errstr), e);
    304         dbgmsg ("Error: select (%d) %s", e, errstr);
     297  if (!r_fd_set->fd_count && !w_fd_set->fd_count && !c_fd_set->fd_count)
     298    {
     299      const long int msec = t->tv_sec*1000 + t->tv_usec/1000;
     300      tr_wait_msec (msec);
     301    }
     302  else if (select (0, r_fd_set->fd_count ? r_fd_set : NULL,
     303                      w_fd_set->fd_count ? w_fd_set : NULL,
     304                      c_fd_set->fd_count ? c_fd_set : NULL, t) < 0)
     305    {
     306      char errstr[512];
     307      const int e = EVUTIL_SOCKET_ERROR ();
     308      tr_net_strerror (errstr, sizeof (errstr), e);
     309      dbgmsg ("Error: select (%d) %s", e, errstr);
    305310    }
    306311#else
    307     select (nfds, r_fd_set, w_fd_set, c_fd_set, t);
     312  select (nfds, r_fd_set, w_fd_set, c_fd_set, t);
    308313#endif
    309314}
     
    312317tr_webThreadFunc (void * vsession)
    313318{
    314     CURLM * multi;
    315     struct tr_web * web;
    316     int taskCount = 0;
    317     struct tr_web_task * task;
    318     tr_session * session = vsession;
    319 
    320     /* try to enable ssl for https support; but if that fails,
    321      * try a plain vanilla init */
    322     if (curl_global_init (CURL_GLOBAL_SSL))
    323         curl_global_init (0);
    324 
    325     web = tr_new0 (struct tr_web, 1);
    326     web->close_mode = ~0;
    327     web->taskLock = tr_lockNew ();
    328     web->tasks = NULL;
    329     web->curl_verbose = getenv ("TR_CURL_VERBOSE") != NULL;
    330     web->curl_ssl_verify = getenv ("TR_CURL_SSL_VERIFY") != NULL;
    331     web->curl_ca_bundle = getenv ("CURL_CA_BUNDLE");
    332     if (web->curl_ssl_verify) {
    333         tr_ninf ("web", "will verify tracker certs using envvar CURL_CA_BUNDLE: %s",
    334                   web->curl_ca_bundle == NULL ? "none" : web->curl_ca_bundle);
    335         tr_ninf ("web", "NB: this only works if you built against libcurl with openssl or gnutls, NOT nss");
    336         tr_ninf ("web", "NB: invalid certs will show up as 'Could not connect to tracker' like many other errors");
    337     }
    338     web->cookie_filename = tr_buildPath (session->configDir, "cookies.txt", NULL);
    339 
    340     multi = curl_multi_init ();
    341     session->web = web;
    342 
    343     for (;;)
    344     {
    345         long msec;
    346         int unused;
    347         CURLMsg * msg;
    348         CURLMcode mcode;
    349 
    350         if (web->close_mode == TR_WEB_CLOSE_NOW)
    351             break;
    352         if ((web->close_mode == TR_WEB_CLOSE_WHEN_IDLE) && (web->tasks == NULL))
    353             break;
    354 
    355         /* add tasks from the queue */
    356         tr_lockLock (web->taskLock);
    357         while (web->tasks != NULL)
     319  CURLM * multi;
     320  struct tr_web * web;
     321  int taskCount = 0;
     322  struct tr_web_task * task;
     323  tr_session * session = vsession;
     324
     325  /* try to enable ssl for https support; but if that fails,
     326   * try a plain vanilla init */
     327  if (curl_global_init (CURL_GLOBAL_SSL))
     328    curl_global_init (0);
     329
     330  web = tr_new0 (struct tr_web, 1);
     331  web->close_mode = ~0;
     332  web->taskLock = tr_lockNew ();
     333  web->tasks = NULL;
     334  web->curl_verbose = getenv ("TR_CURL_VERBOSE") != NULL;
     335  web->curl_ssl_verify = getenv ("TR_CURL_SSL_VERIFY") != NULL;
     336  web->curl_ca_bundle = getenv ("CURL_CA_BUNDLE");
     337  if (web->curl_ssl_verify)
     338    {
     339      tr_ninf ("web", "will verify tracker certs using envvar CURL_CA_BUNDLE: %s",
     340               web->curl_ca_bundle == NULL ? "none" : web->curl_ca_bundle);
     341      tr_ninf ("web", "NB: this only works if you built against libcurl with openssl or gnutls, NOT nss");
     342      tr_ninf ("web", "NB: invalid certs will show up as 'Could not connect to tracker' like many other errors");
     343    }
     344  web->cookie_filename = tr_buildPath (session->configDir, "cookies.txt", NULL);
     345
     346  multi = curl_multi_init ();
     347  session->web = web;
     348
     349  for (;;)
     350    {
     351      long msec;
     352      int unused;
     353      CURLMsg * msg;
     354      CURLMcode mcode;
     355
     356      if (web->close_mode == TR_WEB_CLOSE_NOW)
     357        break;
     358      if ((web->close_mode == TR_WEB_CLOSE_WHEN_IDLE) && (web->tasks == NULL))
     359        break;
     360
     361      /* add tasks from the queue */
     362      tr_lockLock (web->taskLock);
     363      while (web->tasks != NULL)
    358364        {
    359             /* pop the task */
    360             task = web->tasks;
    361             web->tasks = task->next;
    362             task->next = NULL;
    363 
    364             dbgmsg ("adding task to curl: [%s]", task->url);
    365             curl_multi_add_handle (multi, createEasy (session, web, task));
    366             /*fprintf (stderr, "adding a task.. taskCount is now %d\n", taskCount);*/
    367             ++taskCount;
     365          /* pop the task */
     366          task = web->tasks;
     367          web->tasks = task->next;
     368          task->next = NULL;
     369
     370          dbgmsg ("adding task to curl: [%s]", task->url);
     371          curl_multi_add_handle (multi, createEasy (session, web, task));
     372          /*fprintf (stderr, "adding a task.. taskCount is now %d\n", taskCount);*/
     373          ++taskCount;
    368374        }
    369         tr_lockUnlock (web->taskLock);
    370 
    371         /* maybe wait a little while before calling curl_multi_perform () */
    372         msec = 0;
    373         curl_multi_timeout (multi, &msec);
    374         if (msec < 0)
     375      tr_lockUnlock (web->taskLock);
     376
     377      /* maybe wait a little while before calling curl_multi_perform () */
     378      msec = 0;
     379      curl_multi_timeout (multi, &msec);
     380      if (msec < 0)
     381        msec = THREADFUNC_MAX_SLEEP_MSEC;
     382      if (session->isClosed)
     383        msec = 100; /* on shutdown, call perform () more frequently */
     384      if (msec > 0)
     385        {
     386          int usec;
     387          int max_fd;
     388          struct timeval t;
     389          fd_set r_fd_set, w_fd_set, c_fd_set;
     390
     391          max_fd = 0;
     392          FD_ZERO (&r_fd_set);
     393          FD_ZERO (&w_fd_set);
     394          FD_ZERO (&c_fd_set);
     395          curl_multi_fdset (multi, &r_fd_set, &w_fd_set, &c_fd_set, &max_fd);
     396
     397          if (msec > THREADFUNC_MAX_SLEEP_MSEC)
    375398            msec = THREADFUNC_MAX_SLEEP_MSEC;
    376         if (session->isClosed)
    377             msec = 100; /* on shutdown, call perform () more frequently */
    378         if (msec > 0)
     399
     400          usec = msec * 1000;
     401          t.tv_sec =  usec / 1000000;
     402          t.tv_usec = usec % 1000000;
     403          tr_select (max_fd+1, &r_fd_set, &w_fd_set, &c_fd_set, &t);
     404        }
     405
     406      /* call curl_multi_perform () */
     407      do
     408        mcode = curl_multi_perform (multi, &unused);
     409      while (mcode == CURLM_CALL_MULTI_PERFORM);
     410
     411      /* pump completed tasks from the multi */
     412      while ((msg = curl_multi_info_read (multi, &unused)))
    379413        {
    380             int usec;
    381             int max_fd;
    382             struct timeval t;
    383             fd_set r_fd_set, w_fd_set, c_fd_set;
    384 
    385             max_fd = 0;
    386             FD_ZERO (&r_fd_set);
    387             FD_ZERO (&w_fd_set);
    388             FD_ZERO (&c_fd_set);
    389             curl_multi_fdset (multi, &r_fd_set, &w_fd_set, &c_fd_set, &max_fd);
    390 
    391             if (msec > THREADFUNC_MAX_SLEEP_MSEC)
    392                 msec = THREADFUNC_MAX_SLEEP_MSEC;
    393 
    394             usec = msec * 1000;
    395             t.tv_sec =  usec / 1000000;
    396             t.tv_usec = usec % 1000000;
    397             tr_select (max_fd+1, &r_fd_set, &w_fd_set, &c_fd_set, &t);
    398         }
    399 
    400         /* call curl_multi_perform () */
    401         do {
    402             mcode = curl_multi_perform (multi, &unused);
    403         } while (mcode == CURLM_CALL_MULTI_PERFORM);
    404 
    405         /* pump completed tasks from the multi */
    406         while ((msg = curl_multi_info_read (multi, &unused)))
    407         {
    408             if ((msg->msg == CURLMSG_DONE) && (msg->easy_handle != NULL))
     414          if ((msg->msg == CURLMSG_DONE) && (msg->easy_handle != NULL))
    409415            {
    410                 double total_time;
    411                 struct tr_web_task * task;
    412                 long req_bytes_sent;
    413                 CURL * e = msg->easy_handle;
    414                 curl_easy_getinfo (e, CURLINFO_PRIVATE, (void*)&task);
    415                 curl_easy_getinfo (e, CURLINFO_RESPONSE_CODE, &task->code);
    416                 curl_easy_getinfo (e, CURLINFO_REQUEST_SIZE, &req_bytes_sent);
    417                 curl_easy_getinfo (e, CURLINFO_TOTAL_TIME, &total_time);
    418                 task->did_connect = task->code>0 || req_bytes_sent>0;
    419                 task->did_timeout = !task->code && (total_time >= task->timeout_secs);
    420                 curl_multi_remove_handle (multi, e);
    421                 curl_easy_cleanup (e);
    422 /*fprintf (stderr, "removing a completed task.. taskCount is now %d (response code: %d, response len: %d)\n", taskCount, (int)task->code, (int)evbuffer_get_length (task->response));*/
    423                 tr_runInEventThread (task->session, task_finish_func, task);
    424                 --taskCount;
     416              double total_time;
     417              struct tr_web_task * task;
     418              long req_bytes_sent;
     419              CURL * e = msg->easy_handle;
     420              curl_easy_getinfo (e, CURLINFO_PRIVATE, (void*)&task);
     421              curl_easy_getinfo (e, CURLINFO_RESPONSE_CODE, &task->code);
     422              curl_easy_getinfo (e, CURLINFO_REQUEST_SIZE, &req_bytes_sent);
     423              curl_easy_getinfo (e, CURLINFO_TOTAL_TIME, &total_time);
     424              task->did_connect = task->code>0 || req_bytes_sent>0;
     425              task->did_timeout = !task->code && (total_time >= task->timeout_secs);
     426              curl_multi_remove_handle (multi, e);
     427              curl_easy_cleanup (e);
     428              tr_runInEventThread (task->session, task_finish_func, task);
     429              --taskCount;
    425430            }
    426431        }
    427432    }
    428433
    429     /* Discard any remaining tasks.
    430      * This is rare, but can happen on shutdown with unresponsive trackers. */
    431     while (web->tasks != NULL) {
    432         task = web->tasks;
    433         web->tasks = task->next;
    434         dbgmsg ("Discarding task \"%s\"", task->url);
    435         task_free (task);
    436     }
    437 
    438     /* cleanup */
    439     curl_multi_cleanup (multi);
    440     tr_lockFree (web->taskLock);
    441     tr_free (web->cookie_filename);
    442     tr_free (web);
    443     session->web = NULL;
     434  /* Discard any remaining tasks.
     435   * This is rare, but can happen on shutdown with unresponsive trackers. */
     436  while (web->tasks != NULL)
     437    {
     438      task = web->tasks;
     439      web->tasks = task->next;
     440      dbgmsg ("Discarding task \"%s\"", task->url);
     441      task_free (task);
     442    }
     443
     444  /* cleanup */
     445  curl_multi_cleanup (multi);
     446  tr_lockFree (web->taskLock);
     447  tr_free (web->cookie_filename);
     448  tr_free (web);
     449  session->web = NULL;
    444450}
    445451
     
    447453tr_webInit (tr_session * session)
    448454{
    449     tr_threadNew (tr_webThreadFunc, session);
     455  tr_threadNew (tr_webThreadFunc, session);
    450456}
    451457
     
    453459tr_webClose (tr_session * session, tr_web_close_mode close_mode)
    454460{
    455     if (session->web != NULL)
    456     {
    457         session->web->close_mode = close_mode;
    458 
    459         if (close_mode == TR_WEB_CLOSE_NOW)
    460             while (session->web != NULL)
    461                 tr_wait_msec (100);
     461  if (session->web != NULL)
     462    {
     463      session->web->close_mode = close_mode;
     464
     465      if (close_mode == TR_WEB_CLOSE_NOW)
     466        while (session->web != NULL)
     467          tr_wait_msec (100);
    462468    }
    463469}
     
    466472tr_webGetTaskInfo (struct tr_web_task * task, tr_web_task_info info, void * dst)
    467473{
    468     curl_easy_getinfo (task->curl_easy, (CURLINFO) info, dst);
     474  curl_easy_getinfo (task->curl_easy, (CURLINFO) info, dst);
    469475}
    470476
     
    477483tr_webGetResponseStr (long code)
    478484{
    479     switch (code)
    480     {
    481         case   0: return "No Response";
    482         case 101: return "Switching Protocols";
    483         case 200: return "OK";
    484         case 201: return "Created";
    485         case 202: return "Accepted";
    486         case 203: return "Non-Authoritative Information";
    487         case 204: return "No Content";
    488         case 205: return "Reset Content";
    489         case 206: return "Partial Content";
    490         case 300: return "Multiple Choices";
    491         case 301: return "Moved Permanently";
    492         case 302: return "Found";
    493         case 303: return "See Other";
    494         case 304: return "Not Modified";
    495         case 305: return "Use Proxy";
    496         case 306: return " (Unused)";
    497         case 307: return "Temporary Redirect";
    498         case 400: return "Bad Request";
    499         case 401: return "Unauthorized";
    500         case 402: return "Payment Required";
    501         case 403: return "Forbidden";
    502         case 404: return "Not Found";
    503         case 405: return "Method Not Allowed";
    504         case 406: return "Not Acceptable";
    505         case 407: return "Proxy Authentication Required";
    506         case 408: return "Request Timeout";
    507         case 409: return "Conflict";
    508         case 410: return "Gone";
    509         case 411: return "Length Required";
    510         case 412: return "Precondition Failed";
    511         case 413: return "Request Entity Too Large";
    512         case 414: return "Request-URI Too Long";
    513         case 415: return "Unsupported Media Type";
    514         case 416: return "Requested Range Not Satisfiable";
    515         case 417: return "Expectation Failed";
    516         case 500: return "Internal Server Error";
    517         case 501: return "Not Implemented";
    518         case 502: return "Bad Gateway";
    519         case 503: return "Service Unavailable";
    520         case 504: return "Gateway Timeout";
    521         case 505: return "HTTP Version Not Supported";
    522         default:  return "Unknown Error";
     485  switch (code)
     486    {
     487      case   0: return "No Response";
     488      case 101: return "Switching Protocols";
     489      case 200: return "OK";
     490      case 201: return "Created";
     491      case 202: return "Accepted";
     492      case 203: return "Non-Authoritative Information";
     493      case 204: return "No Content";
     494      case 205: return "Reset Content";
     495      case 206: return "Partial Content";
     496      case 300: return "Multiple Choices";
     497      case 301: return "Moved Permanently";
     498      case 302: return "Found";
     499      case 303: return "See Other";
     500      case 304: return "Not Modified";
     501      case 305: return "Use Proxy";
     502      case 306: return " (Unused)";
     503      case 307: return "Temporary Redirect";
     504      case 400: return "Bad Request";
     505      case 401: return "Unauthorized";
     506      case 402: return "Payment Required";
     507      case 403: return "Forbidden";
     508      case 404: return "Not Found";
     509      case 405: return "Method Not Allowed";
     510      case 406: return "Not Acceptable";
     511      case 407: return "Proxy Authentication Required";
     512      case 408: return "Request Timeout";
     513      case 409: return "Conflict";
     514      case 410: return "Gone";
     515      case 411: return "Length Required";
     516      case 412: return "Precondition Failed";
     517      case 413: return "Request Entity Too Large";
     518      case 414: return "Request-URI Too Long";
     519      case 415: return "Unsupported Media Type";
     520      case 416: return "Requested Range Not Satisfiable";
     521      case 417: return "Expectation Failed";
     522      case 500: return "Internal Server Error";
     523      case 501: return "Not Implemented";
     524      case 502: return "Bad Gateway";
     525      case 503: return "Service Unavailable";
     526      case 504: return "Gateway Timeout";
     527      case 505: return "HTTP Version Not Supported";
     528      default:  return "Unknown Error";
    523529    }
    524530}
     
    526532void
    527533tr_http_escape (struct evbuffer  * out,
    528                 const char * str, int len, bool escape_slashes)
    529 {
    530     const char * end;
    531 
    532     if ((len < 0) && (str != NULL))
    533         len = strlen (str);
    534 
    535     for (end=str+len; str && str!=end; ++str) {
    536         if ((*str == ',')
    537             || (*str == '-')
    538             || (*str == '.')
    539             || (('0' <= *str) && (*str <= '9'))
    540             || (('A' <= *str) && (*str <= 'Z'))
    541             || (('a' <= *str) && (*str <= 'z'))
    542             || ((*str == '/') && (!escape_slashes)))
    543             evbuffer_add_printf (out, "%c", *str);
    544         else
    545             evbuffer_add_printf (out, "%%%02X", (unsigned)(*str&0xFF));
     534                const char       * str,
     535                int                len,
     536                bool               escape_slashes)
     537{
     538  const char * end;
     539
     540  if ((len < 0) && (str != NULL))
     541    len = strlen (str);
     542
     543  for (end=str+len; str && str!=end; ++str)
     544    {
     545      if ((*str == ',') || (*str == '-')
     546                        || (*str == '.')
     547                        || (('0' <= *str) && (*str <= '9'))
     548                        || (('A' <= *str) && (*str <= 'Z'))
     549                        || (('a' <= *str) && (*str <= 'z'))
     550                        || ((*str == '/') && (!escape_slashes)))
     551        evbuffer_add_printf (out, "%c", *str);
     552      else
     553        evbuffer_add_printf (out, "%%%02X", (unsigned)(*str&0xFF));
    546554    }
    547555}
     
    550558tr_http_unescape (const char * str, int len)
    551559{
    552     char * tmp = curl_unescape (str, len);
    553     char * ret = tr_strdup (tmp);
    554     curl_free (tmp);
    555     return ret;
     560  char * tmp = curl_unescape (str, len);
     561  char * ret = tr_strdup (tmp);
     562  curl_free (tmp);
     563  return ret;
    556564}
    557565
     
    559567is_rfc2396_alnum (uint8_t ch)
    560568{
    561     return ('0' <= ch && ch <= '9')
    562         || ('A' <= ch && ch <= 'Z')
    563         || ('a' <= ch && ch <= 'z')
    564         || ch == '.'
    565         || ch == '-'
    566         || ch == '_'
    567         || ch == '~';
     569  return ('0' <= ch && ch <= '9')
     570      || ('A' <= ch && ch <= 'Z')
     571      || ('a' <= ch && ch <= 'z')
     572      || ch == '.'
     573      || ch == '-'
     574      || ch == '_'
     575      || ch == '~';
    568576}
    569577
     
    571579tr_http_escape_sha1 (char * out, const uint8_t * sha1_digest)
    572580{
    573     const uint8_t * in = sha1_digest;
    574     const uint8_t * end = in + SHA_DIGEST_LENGTH;
    575 
    576     while (in != end)
    577         if (is_rfc2396_alnum (*in))
    578             *out++ = (char) *in++;
    579         else
    580             out += tr_snprintf (out, 4, "%%%02x", (unsigned int)*in++);
    581 
    582     *out = '\0';
    583 }
     581  const uint8_t * in = sha1_digest;
     582  const uint8_t * end = in + SHA_DIGEST_LENGTH;
     583
     584  while (in != end)
     585    if (is_rfc2396_alnum (*in))
     586      *out++ = (char) *in++;
     587    else
     588      out += tr_snprintf (out, 4, "%%%02x", (unsigned int)*in++);
     589
     590  *out = '\0';
     591}
Note: See TracChangeset for help on using the changeset viewer.