#include "utils.h"
#define dbgmsg(...) \
- do { \
- if (tr_deepLoggingIsActive ()) \
- tr_deepLog (__FILE__, __LINE__, NULL, __VA_ARGS__); \
- } while (0)
+ do \
+ { \
+ if (tr_deepLoggingIsActive ()) \
+ tr_deepLog (__FILE__, __LINE__, NULL, __VA_ARGS__); \
+ } \
+ while (0)
/***
****
static unsigned int
getSpeed_Bps (const struct bratecontrol * r, unsigned int interval_msec, uint64_t now)
{
- if (!now)
- now = tr_time_msec ();
+ if (!now)
+ now = tr_time_msec ();
- if (now != r->cache_time)
+ if (now != r->cache_time)
{
- int i = r->newest;
- uint64_t bytes = 0;
- const uint64_t cutoff = now - interval_msec;
- struct bratecontrol * rvolatile = (struct bratecontrol*) r;
+ int i = r->newest;
+ uint64_t bytes = 0;
+ const uint64_t cutoff = now - interval_msec;
+ struct bratecontrol * rvolatile = (struct bratecontrol*) r;
- for (;;)
+ for (;;)
{
- if (r->transfers[i].date <= cutoff)
- break;
+ if (r->transfers[i].date <= cutoff)
+ break;
- bytes += r->transfers[i].size;
+ bytes += r->transfers[i].size;
- if (--i == -1) i = HISTORY_SIZE - 1; /* circular history */
- if (i == r->newest) break; /* we've come all the way around */
+ if (--i == -1)
+ i = HISTORY_SIZE - 1; /* circular history */
+
+ if (i == r->newest)
+ break; /* we've come all the way around */
}
- rvolatile->cache_val = (unsigned int)((bytes * 1000u) / interval_msec);
- rvolatile->cache_time = now;
+ rvolatile->cache_val = (unsigned int)((bytes * 1000u) / interval_msec);
+ rvolatile->cache_time = now;
}
- return r->cache_val;
+ return r->cache_val;
}
static void
bytesUsed (const uint64_t now, struct bratecontrol * r, size_t size)
{
- if (r->transfers[r->newest].date + GRANULARITY_MSEC >= now)
- r->transfers[r->newest].size += size;
- else
+ if (r->transfers[r->newest].date + GRANULARITY_MSEC >= now)
+ {
+ r->transfers[r->newest].size += size;
+ }
+ else
{
- if (++r->newest == HISTORY_SIZE) r->newest = 0;
- r->transfers[r->newest].date = now;
- r->transfers[r->newest].size = size;
+ if (++r->newest == HISTORY_SIZE)
+ r->newest = 0;
+ r->transfers[r->newest].date = now;
+ r->transfers[r->newest].size = size;
}
- /* invalidate cache_val*/
- r->cache_time = 0;
+ /* invalidate cache_val*/
+ r->cache_time = 0;
}
/******
static int
compareBandwidth (const void * va, const void * vb)
{
- const tr_bandwidth * a = va;
- const tr_bandwidth * b = vb;
- return a->uniqueKey - b->uniqueKey;
+ const tr_bandwidth * a = va;
+ const tr_bandwidth * b = vb;
+ return a->uniqueKey - b->uniqueKey;
}
/***
void
tr_bandwidthConstruct (tr_bandwidth * b, tr_session * session, tr_bandwidth * parent)
{
- static unsigned int uniqueKey = 0;
-
- b->session = session;
- b->children = TR_PTR_ARRAY_INIT;
- b->magicNumber = BANDWIDTH_MAGIC_NUMBER;
- b->uniqueKey = uniqueKey++;
- b->band[TR_UP].honorParentLimits = true;
- b->band[TR_DOWN].honorParentLimits = true;
- tr_bandwidthSetParent (b, parent);
+ static unsigned int uniqueKey = 0;
+
+ b->session = session;
+ b->children = TR_PTR_ARRAY_INIT;
+ b->magicNumber = BANDWIDTH_MAGIC_NUMBER;
+ b->uniqueKey = uniqueKey++;
+ b->band[TR_UP].honorParentLimits = true;
+ b->band[TR_DOWN].honorParentLimits = true;
+ tr_bandwidthSetParent (b, parent);
}
void
tr_bandwidthDestruct (tr_bandwidth * b)
{
- assert (tr_isBandwidth (b));
+ assert (tr_isBandwidth (b));
- tr_bandwidthSetParent (b, NULL);
- tr_ptrArrayDestruct (&b->children, NULL);
+ tr_bandwidthSetParent (b, NULL);
+ tr_ptrArrayDestruct (&b->children, NULL);
- memset (b, ~0, sizeof (tr_bandwidth));
+ memset (b, ~0, sizeof (tr_bandwidth));
}
/***
tr_bandwidthSetParent (tr_bandwidth * b,
tr_bandwidth * parent)
{
- assert (tr_isBandwidth (b));
- assert (b != parent);
+ assert (tr_isBandwidth (b));
+ assert (b != parent);
- if (b->parent)
+ if (b->parent)
{
- void * removed;
+ void * removed;
- assert (tr_isBandwidth (b->parent));
+ assert (tr_isBandwidth (b->parent));
- removed = tr_ptrArrayRemoveSorted (&b->parent->children, b, compareBandwidth);
- assert (removed == b);
- assert (tr_ptrArrayFindSorted (&b->parent->children, b, compareBandwidth) == NULL);
+ removed = tr_ptrArrayRemoveSorted (&b->parent->children, b, compareBandwidth);
+ assert (removed == b);
+ assert (tr_ptrArrayFindSorted (&b->parent->children, b, compareBandwidth) == NULL);
- b->parent = NULL;
+ b->parent = NULL;
}
- if (parent)
+ if (parent)
{
- assert (tr_isBandwidth (parent));
- assert (parent->parent != b);
+ assert (tr_isBandwidth (parent));
+ assert (parent->parent != b);
- assert (tr_ptrArrayFindSorted (&parent->children, b, compareBandwidth) == NULL);
- tr_ptrArrayInsertSorted (&parent->children, b, compareBandwidth);
- assert (tr_ptrArrayFindSorted (&parent->children, b, compareBandwidth) == b);
- b->parent = parent;
+ assert (tr_ptrArrayFindSorted (&parent->children, b, compareBandwidth) == NULL);
+ tr_ptrArrayInsertSorted (&parent->children, b, compareBandwidth);
+ assert (tr_ptrArrayFindSorted (&parent->children, b, compareBandwidth) == b);
+ b->parent = parent;
}
}
unsigned int period_msec,
tr_ptrArray * peer_pool)
{
- const tr_priority_t priority = MAX (parent_priority, b->priority);
+ const tr_priority_t priority = MAX (parent_priority, b->priority);
- assert (tr_isBandwidth (b));
- assert (tr_isDirection (dir));
+ assert (tr_isBandwidth (b));
+ assert (tr_isDirection (dir));
- /* set the available bandwidth */
- if (b->band[dir].isLimited)
+ /* set the available bandwidth */
+ if (b->band[dir].isLimited)
{
- const uint64_t nextPulseSpeed = b->band[dir].desiredSpeed_Bps;
- b->band[dir].bytesLeft = (unsigned int)(nextPulseSpeed * period_msec) / 1000u;
+ const uint64_t nextPulseSpeed = b->band[dir].desiredSpeed_Bps;
+ b->band[dir].bytesLeft = (unsigned int)(nextPulseSpeed * period_msec) / 1000u;
}
- /* add this bandwidth's peer, if any, to the peer pool */
- if (b->peer != NULL) {
- b->peer->priority = priority;
- tr_ptrArrayAppend (peer_pool, b->peer);
+ /* add this bandwidth's peer, if any, to the peer pool */
+ if (b->peer != NULL)
+ {
+ b->peer->priority = priority;
+ tr_ptrArrayAppend (peer_pool, b->peer);
}
- /* traverse & repeat for the subtree */
- if (1) {
- int i;
- struct tr_bandwidth ** children = (struct tr_bandwidth**) tr_ptrArrayBase (&b->children);
- const int n = tr_ptrArraySize (&b->children);
- for (i=0; i<n; ++i)
- allocateBandwidth (children[i], priority, dir, period_msec, peer_pool);
+ /* traverse & repeat for the subtree */
+ if (1)
+ {
+ int i;
+ struct tr_bandwidth ** children = (struct tr_bandwidth**) tr_ptrArrayBase (&b->children);
+ const int n = tr_ptrArraySize (&b->children);
+ for (i=0; i<n; ++i)
+ allocateBandwidth (children[i], priority, dir, period_msec, peer_pool);
}
}
static void
phaseOne (tr_ptrArray * peerArray, tr_direction dir)
{
- int n;
- int peerCount = tr_ptrArraySize (peerArray);
- struct tr_peerIo ** peers = (struct tr_peerIo**) tr_ptrArrayBase (peerArray);
-
- /* First phase of IO. Tries to distribute bandwidth fairly to keep faster
- * peers from starving the others. Loop through the peers, giving each a
- * small chunk of bandwidth. Keep looping until we run out of bandwidth
- * and/or peers that can use it */
- n = peerCount;
- dbgmsg ("%d peers to go round-robin for %s", n, (dir==TR_UP?"upload":"download"));
- while (n > 0)
+ int n;
+ int peerCount = tr_ptrArraySize (peerArray);
+ struct tr_peerIo ** peers = (struct tr_peerIo**) tr_ptrArrayBase (peerArray);
+
+ /* First phase of IO. Tries to distribute bandwidth fairly to keep faster
+ * peers from starving the others. Loop through the peers, giving each a
+ * small chunk of bandwidth. Keep looping until we run out of bandwidth
+ * and/or peers that can use it */
+ n = peerCount;
+ dbgmsg ("%d peers to go round-robin for %s", n, (dir==TR_UP?"upload":"download"));
+ while (n > 0)
{
- const int i = tr_cryptoWeakRandInt (n); /* pick a peer at random */
+ const int i = tr_cryptoWeakRandInt (n); /* pick a peer at random */
- /* value of 3000 bytes chosen so that when using uTP we'll send a full-size
- * frame right away and leave enough buffered data for the next frame to go
- * out in a timely manner. */
- const size_t increment = 3000;
+ /* value of 3000 bytes chosen so that when using uTP we'll send a full-size
+ * frame right away and leave enough buffered data for the next frame to go
+ * out in a timely manner. */
+ const size_t increment = 3000;
- const int bytesUsed = tr_peerIoFlush (peers[i], dir, increment);
+ const int bytesUsed = tr_peerIoFlush (peers[i], dir, increment);
- dbgmsg ("peer #%d of %d used %d bytes in this pass", i, n, bytesUsed);
+ dbgmsg ("peer #%d of %d used %d bytes in this pass", i, n, bytesUsed);
- if (bytesUsed != (int)increment) {
- /* peer is done writing for now; move it to the end of the list */
- tr_peerIo * pio = peers[i];
- peers[i] = peers[n-1];
- peers[n-1] = pio;
- --n;
+ if (bytesUsed != (int)increment)
+ {
+ /* peer is done writing for now; move it to the end of the list */
+ tr_peerIo * pio = peers[i];
+ peers[i] = peers[n-1];
+ peers[n-1] = pio;
+ --n;
}
}
}
tr_direction dir,
unsigned int period_msec)
{
- int i, peerCount;
- tr_ptrArray tmp = TR_PTR_ARRAY_INIT;
- tr_ptrArray low = TR_PTR_ARRAY_INIT;
- tr_ptrArray high = TR_PTR_ARRAY_INIT;
- tr_ptrArray normal = TR_PTR_ARRAY_INIT;
- struct tr_peerIo ** peers;
-
- /* allocateBandwidth () is a helper function with two purposes:
- * 1. allocate bandwidth to b and its subtree
- * 2. accumulate an array of all the peerIos from b and its subtree. */
- allocateBandwidth (b, TR_PRI_LOW, dir, period_msec, &tmp);
- peers = (struct tr_peerIo**) tr_ptrArrayBase (&tmp);
- peerCount = tr_ptrArraySize (&tmp);
-
- for (i=0; i<peerCount; ++i)
+ int i, peerCount;
+ tr_ptrArray tmp = TR_PTR_ARRAY_INIT;
+ tr_ptrArray low = TR_PTR_ARRAY_INIT;
+ tr_ptrArray high = TR_PTR_ARRAY_INIT;
+ tr_ptrArray normal = TR_PTR_ARRAY_INIT;
+ struct tr_peerIo ** peers;
+
+ /* allocateBandwidth () is a helper function with two purposes:
+ * 1. allocate bandwidth to b and its subtree
+ * 2. accumulate an array of all the peerIos from b and its subtree. */
+ allocateBandwidth (b, TR_PRI_LOW, dir, period_msec, &tmp);
+ peers = (struct tr_peerIo**) tr_ptrArrayBase (&tmp);
+ peerCount = tr_ptrArraySize (&tmp);
+
+ for (i=0; i<peerCount; ++i)
{
- tr_peerIo * io = peers[i];
- tr_peerIoRef (io);
+ tr_peerIo * io = peers[i];
+ tr_peerIoRef (io);
- tr_peerIoFlushOutgoingProtocolMsgs (io);
+ tr_peerIoFlushOutgoingProtocolMsgs (io);
- switch (io->priority) {
- case TR_PRI_HIGH: tr_ptrArrayAppend (&high, io); /* fall through */
- case TR_PRI_NORMAL: tr_ptrArrayAppend (&normal, io); /* fall through */
- default: tr_ptrArrayAppend (&low, io);
+ switch (io->priority)
+ {
+ case TR_PRI_HIGH: tr_ptrArrayAppend (&high, io); /* fall through */
+ case TR_PRI_NORMAL: tr_ptrArrayAppend (&normal, io); /* fall through */
+ default: tr_ptrArrayAppend (&low, io);
}
}
- /* First phase of IO. Tries to distribute bandwidth fairly to keep faster
- * peers from starving the others. Loop through the peers, giving each a
- * small chunk of bandwidth. Keep looping until we run out of bandwidth
- * and/or peers that can use it */
- phaseOne (&high, dir);
- phaseOne (&normal, dir);
- phaseOne (&low, dir);
-
- /* Second phase of IO. To help us scale in high bandwidth situations,
- * enable on-demand IO for peers with bandwidth left to burn.
- * This on-demand IO is enabled until (1) the peer runs out of bandwidth,
- * or (2) the next tr_bandwidthAllocate () call, when we start over again. */
- for (i=0; i<peerCount; ++i)
- tr_peerIoSetEnabled (peers[i], dir, tr_peerIoHasBandwidthLeft (peers[i], dir));
-
- for (i=0; i<peerCount; ++i)
- tr_peerIoUnref (peers[i]);
-
- /* cleanup */
- tr_ptrArrayDestruct (&normal, NULL);
- tr_ptrArrayDestruct (&high, NULL);
- tr_ptrArrayDestruct (&low, NULL);
- tr_ptrArrayDestruct (&tmp, NULL);
+ /* First phase of IO. Tries to distribute bandwidth fairly to keep faster
+ * peers from starving the others. Loop through the peers, giving each a
+ * small chunk of bandwidth. Keep looping until we run out of bandwidth
+ * and/or peers that can use it */
+ phaseOne (&high, dir);
+ phaseOne (&normal, dir);
+ phaseOne (&low, dir);
+
+ /* Second phase of IO. To help us scale in high bandwidth situations,
+ * enable on-demand IO for peers with bandwidth left to burn.
+ * This on-demand IO is enabled until (1) the peer runs out of bandwidth,
+ * or (2) the next tr_bandwidthAllocate () call, when we start over again. */
+ for (i=0; i<peerCount; ++i)
+ tr_peerIoSetEnabled (peers[i], dir, tr_peerIoHasBandwidthLeft (peers[i], dir));
+
+ for (i=0; i<peerCount; ++i)
+ tr_peerIoUnref (peers[i]);
+
+ /* cleanup */
+ tr_ptrArrayDestruct (&normal, NULL);
+ tr_ptrArrayDestruct (&high, NULL);
+ tr_ptrArrayDestruct (&low, NULL);
+ tr_ptrArrayDestruct (&tmp, NULL);
}
void
tr_bandwidthSetPeer (tr_bandwidth * b, tr_peerIo * peer)
{
- assert (tr_isBandwidth (b));
- assert ((peer == NULL) || tr_isPeerIo (peer));
+ assert (tr_isBandwidth (b));
+ assert ((peer == NULL) || tr_isPeerIo (peer));
- b->peer = peer;
+ b->peer = peer;
}
/***
tr_direction dir,
unsigned int byteCount)
{
- assert (tr_isBandwidth (b));
- assert (tr_isDirection (dir));
+ assert (tr_isBandwidth (b));
+ assert (tr_isDirection (dir));
- if (b)
+ if (b)
{
- if (b->band[dir].isLimited)
+ if (b->band[dir].isLimited)
{
- byteCount = MIN (byteCount, b->band[dir].bytesLeft);
+ byteCount = MIN (byteCount, b->band[dir].bytesLeft);
- /* if we're getting close to exceeding the speed limit,
- * clamp down harder on the bytes available */
- if (byteCount > 0)
+ /* if we're getting close to exceeding the speed limit,
+ * clamp down harder on the bytes available */
+ if (byteCount > 0)
{
- double current;
- double desired;
- double r;
+ double current;
+ double desired;
+ double r;
- if (now == 0)
- now = tr_time_msec ();
+ if (now == 0)
+ now = tr_time_msec ();
- current = tr_bandwidthGetRawSpeed_Bps (b, now, TR_DOWN);
- desired = tr_bandwidthGetDesiredSpeed_Bps (b, TR_DOWN);
- r = desired >= 1 ? current / desired : 0;
+ current = tr_bandwidthGetRawSpeed_Bps (b, now, TR_DOWN);
+ desired = tr_bandwidthGetDesiredSpeed_Bps (b, TR_DOWN);
+ r = desired >= 1 ? current / desired : 0;
- if (r > 1.0) byteCount = 0;
- else if (r > 0.9) byteCount *= 0.8;
- else if (r > 0.8) byteCount *= 0.9;
+ if (r > 1.0) byteCount = 0;
+ else if (r > 0.9) byteCount *= 0.8;
+ else if (r > 0.8) byteCount *= 0.9;
}
}
- if (b->parent && b->band[dir].honorParentLimits && (byteCount > 0))
- byteCount = bandwidthClamp (b->parent, now, dir, byteCount);
+ if (b->parent && b->band[dir].honorParentLimits && (byteCount > 0))
+ byteCount = bandwidthClamp (b->parent, now, dir, byteCount);
}
- return byteCount;
+ return byteCount;
}
unsigned int
tr_bandwidthClamp (const tr_bandwidth * b,
tr_direction dir,
unsigned int byteCount)
{
- return bandwidthClamp (b, 0, dir, byteCount);
+ return bandwidthClamp (b, 0, dir, byteCount);
}
unsigned int
tr_bandwidthGetRawSpeed_Bps (const tr_bandwidth * b, const uint64_t now, const tr_direction dir)
{
- assert (tr_isBandwidth (b));
- assert (tr_isDirection (dir));
+ assert (tr_isBandwidth (b));
+ assert (tr_isDirection (dir));
- return getSpeed_Bps (&b->band[dir].raw, HISTORY_MSEC, now);
+ return getSpeed_Bps (&b->band[dir].raw, HISTORY_MSEC, now);
}
unsigned int
tr_bandwidthGetPieceSpeed_Bps (const tr_bandwidth * b, const uint64_t now, const tr_direction dir)
{
- assert (tr_isBandwidth (b));
- assert (tr_isDirection (dir));
+ assert (tr_isBandwidth (b));
+ assert (tr_isDirection (dir));
- return getSpeed_Bps (&b->band[dir].piece, HISTORY_MSEC, now);
+ return getSpeed_Bps (&b->band[dir].piece, HISTORY_MSEC, now);
}
void
tr_bandwidthUsed (tr_bandwidth * b,
tr_direction dir,
size_t byteCount,
- bool isPieceData,
+ bool isPieceData,
uint64_t now)
{
- struct tr_band * band;
+ struct tr_band * band;
- assert (tr_isBandwidth (b));
- assert (tr_isDirection (dir));
+ assert (tr_isBandwidth (b));
+ assert (tr_isDirection (dir));
- band = &b->band[dir];
+ band = &b->band[dir];
- if (band->isLimited && isPieceData)
- band->bytesLeft -= MIN (band->bytesLeft, byteCount);
+ if (band->isLimited && isPieceData)
+ band->bytesLeft -= MIN (band->bytesLeft, byteCount);
#ifdef DEBUG_DIRECTION
if ((dir == DEBUG_DIRECTION) && (band->isLimited))
b, byteCount, (isPieceData?"piece":"raw"), oldBytesLeft, band->bytesLeft);
#endif
- bytesUsed (now, &band->raw, byteCount);
+ bytesUsed (now, &band->raw, byteCount);
- if (isPieceData)
- bytesUsed (now, &band->piece, byteCount);
+ if (isPieceData)
+ bytesUsed (now, &band->piece, byteCount);
- if (b->parent != NULL)
- tr_bandwidthUsed (b->parent, dir, byteCount, isPieceData, now);
+ if (b->parent != NULL)
+ tr_bandwidthUsed (b->parent, dir, byteCount, isPieceData, now);
}
void
tr_sha1 (uint8_t * setme, const void * content1, int content1_len, ...)
{
- va_list vl;
- SHA_CTX sha;
- const void * content;
+ va_list vl;
+ SHA_CTX sha;
+ const void * content;
- SHA1_Init (&sha);
- SHA1_Update (&sha, content1, content1_len);
+ SHA1_Init (&sha);
+ SHA1_Update (&sha, content1, content1_len);
- va_start (vl, content1_len);
- while ((content = va_arg (vl, const void*)))
- SHA1_Update (&sha, content, va_arg (vl, int));
- va_end (vl);
+ va_start (vl, content1_len);
+ while ((content = va_arg (vl, const void*)))
+ SHA1_Update (&sha, content, va_arg (vl, int));
+ va_end (vl);
- SHA1_Final (setme, &sha);
+ SHA1_Final (setme, &sha);
}
/**
static const uint8_t dh_P[PRIME_LEN] =
{
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
- 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
- 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
- 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
- 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
- 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
- 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
- 0xA6, 0x3A, 0x36, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x05, 0x63,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
+ 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
+ 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
+ 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
+ 0xA6, 0x3A, 0x36, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x05, 0x63,
};
static const uint8_t dh_G[] = { 2 };
**/
#define logErrorFromSSL(...) \
- do { \
- if (tr_msgLoggingIsActive (TR_MSG_ERR)) { \
- char buf[512]; \
- ERR_error_string_n (ERR_get_error (), buf, sizeof (buf)); \
- tr_msg (__FILE__, __LINE__, TR_MSG_ERR, MY_NAME, "%s", buf); \
- } \
- } while (0)
+ do { \
+ if (tr_msgLoggingIsActive (TR_MSG_ERR)) { \
+ char buf[512]; \
+ ERR_error_string_n (ERR_get_error (), buf, sizeof (buf)); \
+ tr_msg (__FILE__, __LINE__, TR_MSG_ERR, MY_NAME, "%s", buf); \
+ } \
+ } while (0)
static void
ensureKeyExists (tr_crypto * crypto)
{
- if (crypto->dh == NULL)
+ if (crypto->dh == NULL)
{
- int len, offset;
- DH * dh = DH_new ();
+ int len, offset;
+ DH * dh = DH_new ();
- dh->p = BN_bin2bn (dh_P, sizeof (dh_P), NULL);
- if (dh->p == NULL)
- logErrorFromSSL ();
-
- dh->g = BN_bin2bn (dh_G, sizeof (dh_G), NULL);
- if (dh->g == NULL)
- logErrorFromSSL ();
+ dh->p = BN_bin2bn (dh_P, sizeof (dh_P), NULL);
+ if (dh->p == NULL)
+ logErrorFromSSL ();
- /* private DH value: strong random BN of DH_PRIVKEY_LEN*8 bits */
- dh->priv_key = BN_new ();
- do {
- if (BN_rand (dh->priv_key, DH_PRIVKEY_LEN * 8, -1, 0) != 1)
- logErrorFromSSL ();
- } while (BN_num_bits (dh->priv_key) < DH_PRIVKEY_LEN_MIN * 8);
+ dh->g = BN_bin2bn (dh_G, sizeof (dh_G), NULL);
+ if (dh->g == NULL)
+ logErrorFromSSL ();
- if (!DH_generate_key (dh))
+ /* private DH value: strong random BN of DH_PRIVKEY_LEN*8 bits */
+ dh->priv_key = BN_new ();
+ do
+ {
+ if (BN_rand (dh->priv_key, DH_PRIVKEY_LEN * 8, -1, 0) != 1)
logErrorFromSSL ();
+ }
+ while (BN_num_bits (dh->priv_key) < DH_PRIVKEY_LEN_MIN * 8);
+
+ if (!DH_generate_key (dh))
+ logErrorFromSSL ();
- /* DH can generate key sizes that are smaller than the size of
- P with exponentially decreasing probability, in which case
- the msb's of myPublicKey need to be zeroed appropriately. */
- len = BN_num_bytes (dh->pub_key);
- offset = KEY_LEN - len;
- assert (len <= KEY_LEN);
- memset (crypto->myPublicKey, 0, offset);
- BN_bn2bin (dh->pub_key, crypto->myPublicKey + offset);
+ /* DH can generate key sizes that are smaller than the size of
+ P with exponentially decreasing probability, in which case
+ the msb's of myPublicKey need to be zeroed appropriately. */
+ len = BN_num_bytes (dh->pub_key);
+ offset = KEY_LEN - len;
+ assert (len <= KEY_LEN);
+ memset (crypto->myPublicKey, 0, offset);
+ BN_bn2bin (dh->pub_key, crypto->myPublicKey + offset);
- crypto->dh = dh;
+ crypto->dh = dh;
}
}
void
tr_cryptoConstruct (tr_crypto * crypto, const uint8_t * torrentHash, bool isIncoming)
{
- memset (crypto, 0, sizeof (tr_crypto));
+ memset (crypto, 0, sizeof (tr_crypto));
- crypto->dh = NULL;
- crypto->isIncoming = isIncoming;
- tr_cryptoSetTorrentHash (crypto, torrentHash);
+ crypto->dh = NULL;
+ crypto->isIncoming = isIncoming;
+ tr_cryptoSetTorrentHash (crypto, torrentHash);
}
void
tr_cryptoDestruct (tr_crypto * crypto)
{
- if (crypto->dh != NULL)
- DH_free (crypto->dh);
+ if (crypto->dh != NULL)
+ DH_free (crypto->dh);
}
/**
tr_cryptoComputeSecret (tr_crypto * crypto,
const uint8_t * peerPublicKey)
{
- int len;
- uint8_t secret[KEY_LEN];
- BIGNUM * bn = BN_bin2bn (peerPublicKey, KEY_LEN, NULL);
- DH * dh;
+ DH * dh;
+ int len;
+ uint8_t secret[KEY_LEN];
+ BIGNUM * bn = BN_bin2bn (peerPublicKey, KEY_LEN, NULL);
- ensureKeyExists (crypto);
- dh = crypto->dh;
+ ensureKeyExists (crypto);
+ dh = crypto->dh;
- assert (DH_size (dh) == KEY_LEN);
+ assert (DH_size (dh) == KEY_LEN);
- len = DH_compute_key (secret, bn, dh);
- if (len == -1)
- logErrorFromSSL ();
- else {
- int offset;
- assert (len <= KEY_LEN);
- offset = KEY_LEN - len;
- memset (crypto->mySecret, 0, offset);
- memcpy (crypto->mySecret + offset, secret, len);
- crypto->mySecretIsSet = 1;
+ len = DH_compute_key (secret, bn, dh);
+ if (len == -1)
+ {
+ logErrorFromSSL ();
+ }
+ else
+ {
+ int offset;
+ assert (len <= KEY_LEN);
+ offset = KEY_LEN - len;
+ memset (crypto->mySecret, 0, offset);
+ memcpy (crypto->mySecret + offset, secret, len);
+ crypto->mySecretIsSet = 1;
}
- BN_free (bn);
- return crypto->mySecret;
+ BN_free (bn);
+ return crypto->mySecret;
}
const uint8_t*
tr_cryptoGetMyPublicKey (const tr_crypto * crypto,
- int * setme_len)
+ int * setme_len)
{
- ensureKeyExists ((tr_crypto *) crypto);
- *setme_len = KEY_LEN;
- return crypto->myPublicKey;
+ ensureKeyExists ((tr_crypto *) crypto);
+ *setme_len = KEY_LEN;
+ return crypto->myPublicKey;
}
/**
**/
static void
-initRC4 (tr_crypto * crypto,
- RC4_KEY * setme,
+initRC4 (tr_crypto * crypto,
+ RC4_KEY * setme,
const char * key)
{
- SHA_CTX sha;
- uint8_t buf[SHA_DIGEST_LENGTH];
+ SHA_CTX sha;
+ uint8_t buf[SHA_DIGEST_LENGTH];
- assert (crypto->torrentHashIsSet);
- assert (crypto->mySecretIsSet);
+ assert (crypto->torrentHashIsSet);
+ assert (crypto->mySecretIsSet);
- if (SHA1_Init (&sha)
- && SHA1_Update (&sha, key, 4)
- && SHA1_Update (&sha, crypto->mySecret, KEY_LEN)
- && SHA1_Update (&sha, crypto->torrentHash, SHA_DIGEST_LENGTH)
- && SHA1_Final (buf, &sha))
+ if (SHA1_Init (&sha)
+ && SHA1_Update (&sha, key, 4)
+ && SHA1_Update (&sha, crypto->mySecret, KEY_LEN)
+ && SHA1_Update (&sha, crypto->torrentHash, SHA_DIGEST_LENGTH)
+ && SHA1_Final (buf, &sha))
{
- RC4_set_key (setme, SHA_DIGEST_LENGTH, buf);
+ RC4_set_key (setme, SHA_DIGEST_LENGTH, buf);
}
- else
+ else
{
- logErrorFromSSL ();
+ logErrorFromSSL ();
}
}
void
tr_cryptoDecryptInit (tr_crypto * crypto)
{
- unsigned char discard[1024];
- const char * txt = crypto->isIncoming ? "keyA" : "keyB";
+ unsigned char discard[1024];
+ const char * txt = crypto->isIncoming ? "keyA" : "keyB";
- initRC4 (crypto, &crypto->dec_key, txt);
- RC4 (&crypto->dec_key, sizeof (discard), discard, discard);
+ initRC4 (crypto, &crypto->dec_key, txt);
+ RC4 (&crypto->dec_key, sizeof (discard), discard, discard);
}
void
-tr_cryptoDecrypt (tr_crypto * crypto,
+tr_cryptoDecrypt (tr_crypto * crypto,
size_t buf_len,
const void * buf_in,
- void * buf_out)
+ void * buf_out)
{
- RC4 (&crypto->dec_key, buf_len,
+ RC4 (&crypto->dec_key, buf_len,
(const unsigned char*)buf_in,
(unsigned char*)buf_out);
}
void
tr_cryptoEncryptInit (tr_crypto * crypto)
{
- unsigned char discard[1024];
- const char * txt = crypto->isIncoming ? "keyB" : "keyA";
+ unsigned char discard[1024];
+ const char * txt = crypto->isIncoming ? "keyB" : "keyA";
- initRC4 (crypto, &crypto->enc_key, txt);
- RC4 (&crypto->enc_key, sizeof (discard), discard, discard);
+ initRC4 (crypto, &crypto->enc_key, txt);
+ RC4 (&crypto->enc_key, sizeof (discard), discard, discard);
}
void
-tr_cryptoEncrypt (tr_crypto * crypto,
+tr_cryptoEncrypt (tr_crypto * crypto,
size_t buf_len,
const void * buf_in,
- void * buf_out)
+ void * buf_out)
{
- RC4 (&crypto->enc_key, buf_len,
+ RC4 (&crypto->enc_key, buf_len,
(const unsigned char*)buf_in,
(unsigned char*)buf_out);
}
**/
void
-tr_cryptoSetTorrentHash (tr_crypto * crypto,
+tr_cryptoSetTorrentHash (tr_crypto * crypto,
const uint8_t * hash)
{
- crypto->torrentHashIsSet = hash ? 1 : 0;
+ crypto->torrentHashIsSet = hash ? 1 : 0;
- if (hash)
- memcpy (crypto->torrentHash, hash, SHA_DIGEST_LENGTH);
- else
- memset (crypto->torrentHash, 0, SHA_DIGEST_LENGTH);
+ if (hash)
+ memcpy (crypto->torrentHash, hash, SHA_DIGEST_LENGTH);
+ else
+ memset (crypto->torrentHash, 0, SHA_DIGEST_LENGTH);
}
const uint8_t*
tr_cryptoGetTorrentHash (const tr_crypto * crypto)
{
- assert (crypto);
- assert (crypto->torrentHashIsSet);
+ assert (crypto);
+ assert (crypto->torrentHashIsSet);
- return crypto->torrentHash;
+ return crypto->torrentHash;
}
int
tr_cryptoHasTorrentHash (const tr_crypto * crypto)
{
- assert (crypto);
+ assert (crypto);
- return crypto->torrentHashIsSet ? 1 : 0;
+ return crypto->torrentHashIsSet ? 1 : 0;
}
int
tr_cryptoRandInt (int upperBound)
{
- int noise;
- int val;
+ int noise;
+ int val;
- assert (upperBound > 0);
+ assert (upperBound > 0);
- if (RAND_pseudo_bytes ((unsigned char *) &noise, sizeof noise) >= 0)
+ if (RAND_pseudo_bytes ((unsigned char *) &noise, sizeof noise) >= 0)
{
- val = abs (noise) % upperBound;
+ val = abs (noise) % upperBound;
}
- else /* fall back to a weaker implementation... */
+ else /* fall back to a weaker implementation... */
{
- val = tr_cryptoWeakRandInt (upperBound);
+ val = tr_cryptoWeakRandInt (upperBound);
}
- return val;
+ return val;
}
int
tr_cryptoWeakRandInt (int upperBound)
{
- static bool init = false;
+ static bool init = false;
- assert (upperBound > 0);
+ assert (upperBound > 0);
- if (!init)
+ if (!init)
{
- srand (tr_time_msec ());
- init = true;
+ srand (tr_time_msec ());
+ init = true;
}
- return rand () % upperBound;
+ return rand () % upperBound;
}
void
tr_cryptoRandBuf (void * buf, size_t len)
{
- if (RAND_pseudo_bytes ((unsigned char*)buf, len) != 1)
- logErrorFromSSL ();
+ if (RAND_pseudo_bytes ((unsigned char*)buf, len) != 1)
+ logErrorFromSSL ();
}
/***
char*
tr_ssha1 (const void * plaintext)
{
- enum { saltval_len = 8,
- salter_len = 64 };
- static const char * salter = "0123456789"
- "abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "./";
-
- size_t i;
- unsigned char salt[saltval_len];
- uint8_t sha[SHA_DIGEST_LENGTH];
- char buf[2*SHA_DIGEST_LENGTH + saltval_len + 2];
-
- tr_cryptoRandBuf (salt, saltval_len);
- for (i=0; i<saltval_len; ++i)
- salt[i] = salter[ salt[i] % salter_len ];
-
- tr_sha1 (sha, plaintext, strlen (plaintext), salt, saltval_len, NULL);
- tr_sha1_to_hex (&buf[1], sha);
- memcpy (&buf[1+2*SHA_DIGEST_LENGTH], &salt, saltval_len);
- buf[1+2*SHA_DIGEST_LENGTH + saltval_len] = '\0';
- buf[0] = '{'; /* signal that this is a hash. this makes saving/restoring
- easier */
-
- return tr_strdup (&buf);
+ enum { saltval_len = 8,
+ salter_len = 64 };
+ static const char * salter = "0123456789"
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "./";
+
+ size_t i;
+ unsigned char salt[saltval_len];
+ uint8_t sha[SHA_DIGEST_LENGTH];
+ char buf[2*SHA_DIGEST_LENGTH + saltval_len + 2];
+
+ tr_cryptoRandBuf (salt, saltval_len);
+ for (i=0; i<saltval_len; ++i)
+ salt[i] = salter[ salt[i] % salter_len ];
+
+ tr_sha1 (sha, plaintext, strlen (plaintext), salt, saltval_len, NULL);
+ tr_sha1_to_hex (&buf[1], sha);
+ memcpy (&buf[1+2*SHA_DIGEST_LENGTH], &salt, saltval_len);
+ buf[1+2*SHA_DIGEST_LENGTH + saltval_len] = '\0';
+ buf[0] = '{'; /* signal that this is a hash. this makes saving/restoring easier */
+
+ return tr_strdup (&buf);
}
bool
tr_ssha1_matches (const char * source, const char * pass)
{
- char * salt;
- size_t saltlen;
- char * hashed;
- uint8_t buf[SHA_DIGEST_LENGTH];
- bool result;
- const size_t sourcelen = strlen (source);
-
- /* extract the salt */
- if (sourcelen < 2*SHA_DIGEST_LENGTH-1)
- return false;
- saltlen = sourcelen - 2*SHA_DIGEST_LENGTH-1;
- salt = tr_malloc (saltlen);
- memcpy (salt, source + 2*SHA_DIGEST_LENGTH+1, saltlen);
-
- /* hash pass + salt */
- hashed = tr_malloc (2*SHA_DIGEST_LENGTH + saltlen + 2);
- tr_sha1 (buf, pass, strlen (pass), salt, saltlen, NULL);
- tr_sha1_to_hex (&hashed[1], buf);
- memcpy (hashed + 1+2*SHA_DIGEST_LENGTH, salt, saltlen);
- hashed[1+2*SHA_DIGEST_LENGTH + saltlen] = '\0';
- hashed[0] = '{';
-
- result = strcmp (source, hashed) == 0 ? true : false;
-
- tr_free (hashed);
- tr_free (salt);
-
- return result;
+ char * salt;
+ size_t saltlen;
+ char * hashed;
+ uint8_t buf[SHA_DIGEST_LENGTH];
+ bool result;
+ const size_t sourcelen = strlen (source);
+
+ /* extract the salt */
+ if (sourcelen < 2*SHA_DIGEST_LENGTH-1)
+ return false;
+ saltlen = sourcelen - 2*SHA_DIGEST_LENGTH-1;
+ salt = tr_malloc (saltlen);
+ memcpy (salt, source + 2*SHA_DIGEST_LENGTH+1, saltlen);
+
+ /* hash pass + salt */
+ hashed = tr_malloc (2*SHA_DIGEST_LENGTH + saltlen + 2);
+ tr_sha1 (buf, pass, strlen (pass), salt, saltlen, NULL);
+ tr_sha1_to_hex (&hashed[1], buf);
+ memcpy (hashed + 1+2*SHA_DIGEST_LENGTH, salt, saltlen);
+ hashed[1+2*SHA_DIGEST_LENGTH + saltlen] = '\0';
+ hashed[0] = '{';
+
+ result = strcmp (source, hashed) == 0 ? true : false;
+
+ tr_free (hashed);
+ tr_free (salt);
+
+ return result;
}
enum
{
- /* how frequently to cull old atoms */
- ATOM_PERIOD_MSEC = (60 * 1000),
+ /* how frequently to cull old atoms */
+ ATOM_PERIOD_MSEC = (60 * 1000),
- /* how frequently to change which peers are choked */
- RECHOKE_PERIOD_MSEC = (10 * 1000),
+ /* how frequently to change which peers are choked */
+ RECHOKE_PERIOD_MSEC = (10 * 1000),
- /* an optimistically unchoked peer is immune from rechoking
- for this many calls to rechokeUploads (). */
- OPTIMISTIC_UNCHOKE_MULTIPLIER = 4,
+ /* an optimistically unchoked peer is immune from rechoking
+ for this many calls to rechokeUploads (). */
+ OPTIMISTIC_UNCHOKE_MULTIPLIER = 4,
- /* how frequently to reallocate bandwidth */
- BANDWIDTH_PERIOD_MSEC = 500,
+ /* how frequently to reallocate bandwidth */
+ BANDWIDTH_PERIOD_MSEC = 500,
- /* how frequently to age out old piece request lists */
- REFILL_UPKEEP_PERIOD_MSEC = (10 * 1000),
+ /* how frequently to age out old piece request lists */
+ REFILL_UPKEEP_PERIOD_MSEC = (10 * 1000),
- /* how frequently to decide which peers live and die */
- RECONNECT_PERIOD_MSEC = 500,
+ /* how frequently to decide which peers live and die */
+ RECONNECT_PERIOD_MSEC = 500,
- /* when many peers are available, keep idle ones this long */
- MIN_UPLOAD_IDLE_SECS = (60),
+ /* when many peers are available, keep idle ones this long */
+ MIN_UPLOAD_IDLE_SECS = (60),
- /* when few peers are available, keep idle ones this long */
- MAX_UPLOAD_IDLE_SECS = (60 * 5),
+ /* when few peers are available, keep idle ones this long */
+ MAX_UPLOAD_IDLE_SECS = (60 * 5),
- /* max number of peers to ask for per second overall.
- * this throttle is to avoid overloading the router */
- MAX_CONNECTIONS_PER_SECOND = 12,
+ /* max number of peers to ask for per second overall.
+ * this throttle is to avoid overloading the router */
+ MAX_CONNECTIONS_PER_SECOND = 12,
- MAX_CONNECTIONS_PER_PULSE = (int)(MAX_CONNECTIONS_PER_SECOND * (RECONNECT_PERIOD_MSEC/1000.0)),
+ MAX_CONNECTIONS_PER_PULSE = (int)(MAX_CONNECTIONS_PER_SECOND * (RECONNECT_PERIOD_MSEC/1000.0)),
- /* number of bad pieces a peer is allowed to send before we ban them */
- MAX_BAD_PIECES_PER_PEER = 5,
+ /* number of bad pieces a peer is allowed to send before we ban them */
+ MAX_BAD_PIECES_PER_PEER = 5,
- /* amount of time to keep a list of request pieces lying around
- before it's considered too old and needs to be rebuilt */
- PIECE_LIST_SHELF_LIFE_SECS = 60,
+ /* amount of time to keep a list of request pieces lying around
+ before it's considered too old and needs to be rebuilt */
+ PIECE_LIST_SHELF_LIFE_SECS = 60,
- /* use for bitwise operations w/peer_atom.flags2 */
- MYFLAG_BANNED = 1,
+ /* use for bitwise operations w/peer_atom.flags2 */
+ MYFLAG_BANNED = 1,
- /* use for bitwise operations w/peer_atom.flags2 */
- /* unreachable for now... but not banned.
- * if they try to connect to us it's okay */
- MYFLAG_UNREACHABLE = 2,
+ /* use for bitwise operations w/peer_atom.flags2 */
+ /* unreachable for now... but not banned.
+ * if they try to connect to us it's okay */
+ MYFLAG_UNREACHABLE = 2,
- /* the minimum we'll wait before attempting to reconnect to a peer */
- MINIMUM_RECONNECT_INTERVAL_SECS = 5,
+ /* the minimum we'll wait before attempting to reconnect to a peer */
+ MINIMUM_RECONNECT_INTERVAL_SECS = 5,
- /** how long we'll let requests we've made linger before we cancel them */
- REQUEST_TTL_SECS = 90,
+ /** how long we'll let requests we've made linger before we cancel them */
+ REQUEST_TTL_SECS = 90,
- NO_BLOCKS_CANCEL_HISTORY = 120,
+ NO_BLOCKS_CANCEL_HISTORY = 120,
- CANCEL_HISTORY_SEC = 60
+ CANCEL_HISTORY_SEC = 60
};
const tr_peer_event TR_PEER_EVENT_INIT = { 0, 0, NULL, 0, 0, 0, false, 0 };
*/
struct peer_atom
{
- uint8_t fromFirst; /* where the peer was first found */
- uint8_t fromBest; /* the "best" value of where the peer has been found */
- uint8_t flags; /* these match the added_f flags */
- uint8_t flags2; /* flags that aren't defined in added_f */
- int8_t seedProbability; /* how likely is this to be a seed... [0..100] or -1 for unknown */
- int8_t blocklisted; /* -1 for unknown, true for blocklisted, false for not blocklisted */
-
- tr_port port;
- bool utp_failed; /* We recently failed to connect over uTP */
- uint16_t numFails;
- time_t time; /* when the peer's connection status last changed */
- time_t piece_data_time;
-
- time_t lastConnectionAttemptAt;
- time_t lastConnectionAt;
-
- /* similar to a TTL field, but less rigid --
- * if the swarm is small, the atom will be kept past this date. */
- time_t shelf_date;
- tr_peer * peer; /* will be NULL if not connected */
- tr_address addr;
+ uint8_t fromFirst; /* where the peer was first found */
+ uint8_t fromBest; /* the "best" value of where the peer has been found */
+ uint8_t flags; /* these match the added_f flags */
+ uint8_t flags2; /* flags that aren't defined in added_f */
+ int8_t seedProbability; /* how likely is this to be a seed... [0..100] or -1 for unknown */
+ int8_t blocklisted; /* -1 for unknown, true for blocklisted, false for not blocklisted */
+
+ tr_port port;
+ bool utp_failed; /* We recently failed to connect over uTP */
+ uint16_t numFails;
+ time_t time; /* when the peer's connection status last changed */
+ time_t piece_data_time;
+
+ time_t lastConnectionAttemptAt;
+ time_t lastConnectionAt;
+
+ /* similar to a TTL field, but less rigid --
+ * if the swarm is small, the atom will be kept past this date. */
+ time_t shelf_date;
+ tr_peer * peer; /* will be NULL if not connected */
+ tr_address addr;
};
#ifdef NDEBUG
static bool
tr_isAtom (const struct peer_atom * atom)
{
- return (atom != NULL)
- && (atom->fromFirst < TR_PEER_FROM__MAX)
- && (atom->fromBest < TR_PEER_FROM__MAX)
- && (tr_address_is_valid (&atom->addr));
+ return (atom != NULL)
+ && (atom->fromFirst < TR_PEER_FROM__MAX)
+ && (atom->fromBest < TR_PEER_FROM__MAX)
+ && (tr_address_is_valid (&atom->addr));
}
#endif
static const char*
tr_atomAddrStr (const struct peer_atom * atom)
{
- return atom ? tr_peerIoAddrStr (&atom->addr, atom->port) : "[no atom]";
+ return atom ? tr_peerIoAddrStr (&atom->addr, atom->port) : "[no atom]";
}
struct block_request
{
- tr_block_index_t block;
- tr_peer * peer;
- time_t sentAt;
+ tr_block_index_t block;
+ tr_peer * peer;
+ time_t sentAt;
};
struct weighted_piece
{
- tr_piece_index_t index;
- int16_t salt;
- int16_t requestCount;
+ tr_piece_index_t index;
+ int16_t salt;
+ int16_t requestCount;
};
enum piece_sort_state
{
- PIECES_UNSORTED,
- PIECES_SORTED_BY_INDEX,
- PIECES_SORTED_BY_WEIGHT
+ PIECES_UNSORTED,
+ PIECES_SORTED_BY_INDEX,
+ PIECES_SORTED_BY_WEIGHT
};
/** @brief Opaque, per-torrent data structure for peer connection information */
typedef struct tr_torrent_peers
{
- tr_ptrArray outgoingHandshakes; /* tr_handshake */
- tr_ptrArray pool; /* struct peer_atom */
- tr_ptrArray peers; /* tr_peer */
- tr_ptrArray webseeds; /* tr_webseed */
+ tr_ptrArray outgoingHandshakes; /* tr_handshake */
+ tr_ptrArray pool; /* struct peer_atom */
+ tr_ptrArray peers; /* tr_peer */
+ tr_ptrArray webseeds; /* tr_webseed */
- tr_torrent * tor;
- struct tr_peerMgr * manager;
+ tr_torrent * tor;
+ struct tr_peerMgr * manager;
- tr_peer * optimistic; /* the optimistic peer, or NULL if none */
- int optimisticUnchokeTimeScaler;
+ tr_peer * optimistic; /* the optimistic peer, or NULL if none */
+ int optimisticUnchokeTimeScaler;
- bool isRunning;
- bool needsCompletenessCheck;
+ bool isRunning;
+ bool needsCompletenessCheck;
- struct block_request * requests;
- int requestCount;
- int requestAlloc;
+ struct block_request * requests;
+ int requestCount;
+ int requestAlloc;
- struct weighted_piece * pieces;
- int pieceCount;
- enum piece_sort_state pieceSortState;
+ struct weighted_piece * pieces;
+ int pieceCount;
+ enum piece_sort_state pieceSortState;
- /* An array of pieceCount items stating how many peers have each piece.
- This is used to help us for downloading pieces "rarest first."
- This may be NULL if we don't have metainfo yet, or if we're not
- downloading and don't care about rarity */
- uint16_t * pieceReplication;
- size_t pieceReplicationSize;
+ /* An array of pieceCount items stating how many peers have each piece.
+ This is used to help us for downloading pieces "rarest first."
+ This may be NULL if we don't have metainfo yet, or if we're not
+ downloading and don't care about rarity */
+ uint16_t * pieceReplication;
+ size_t pieceReplicationSize;
- int interestedCount;
- int maxPeers;
- time_t lastCancel;
+ int interestedCount;
+ int maxPeers;
+ time_t lastCancel;
- /* Before the endgame this should be 0. In endgame, is contains the average
- * number of pending requests per peer. Only peers which have more pending
- * requests are considered 'fast' are allowed to request a block that's
- * already been requested from another (slower?) peer. */
- int endgame;
+ /* Before the endgame this should be 0. In endgame, is contains the average
+ * number of pending requests per peer. Only peers which have more pending
+ * requests are considered 'fast' are allowed to request a block that's
+ * already been requested from another (slower?) peer. */
+ int endgame;
}
Torrent;
struct tr_peerMgr
{
- tr_session * session;
- tr_ptrArray incomingHandshakes; /* tr_handshake */
- struct event * bandwidthTimer;
- struct event * rechokeTimer;
- struct event * refillUpkeepTimer;
- struct event * atomTimer;
+ tr_session * session;
+ tr_ptrArray incomingHandshakes; /* tr_handshake */
+ struct event * bandwidthTimer;
+ struct event * rechokeTimer;
+ struct event * refillUpkeepTimer;
+ struct event * atomTimer;
};
#define tordbg(t, ...) \
static inline void
managerLock (const struct tr_peerMgr * manager)
{
- tr_sessionLock (manager->session);
+ tr_sessionLock (manager->session);
}
static inline void
managerUnlock (const struct tr_peerMgr * manager)
{
- tr_sessionUnlock (manager->session);
+ tr_sessionUnlock (manager->session);
}
static inline void
torrentLock (Torrent * torrent)
{
- managerLock (torrent->manager);
+ managerLock (torrent->manager);
}
static inline void
torrentUnlock (Torrent * torrent)
{
- managerUnlock (torrent->manager);
+ managerUnlock (torrent->manager);
}
static inline int
torrentIsLocked (const Torrent * t)
{
- return tr_sessionIsLocked (t->manager->session);
+ return tr_sessionIsLocked (t->manager->session);
}
/**
static int
handshakeCompareToAddr (const void * va, const void * vb)
{
- const tr_handshake * a = va;
+ const tr_handshake * a = va;
- return tr_address_compare (tr_handshakeGetAddr (a, NULL), vb);
+ return tr_address_compare (tr_handshakeGetAddr (a, NULL), vb);
}
static int
handshakeCompare (const void * a, const void * b)
{
- return handshakeCompareToAddr (a, tr_handshakeGetAddr (b, NULL));
+ return handshakeCompareToAddr (a, tr_handshakeGetAddr (b, NULL));
}
static inline tr_handshake*
getExistingHandshake (tr_ptrArray * handshakes, const tr_address * addr)
{
- if (tr_ptrArrayEmpty (handshakes))
- return NULL;
+ if (tr_ptrArrayEmpty (handshakes))
+ return NULL;
- return tr_ptrArrayFindSorted (handshakes, addr, handshakeCompareToAddr);
+ return tr_ptrArrayFindSorted (handshakes, addr, handshakeCompareToAddr);
}
static int
comparePeerAtomToAddress (const void * va, const void * vb)
{
- const struct peer_atom * a = va;
+ const struct peer_atom * a = va;
- return tr_address_compare (&a->addr, vb);
+ return tr_address_compare (&a->addr, vb);
}
static int
compareAtomsByAddress (const void * va, const void * vb)
{
- const struct peer_atom * b = vb;
+ const struct peer_atom * b = vb;
- assert (tr_isAtom (b));
+ assert (tr_isAtom (b));
- return comparePeerAtomToAddress (va, &b->addr);
+ return comparePeerAtomToAddress (va, &b->addr);
}
/**
const tr_address *
tr_peerAddress (const tr_peer * peer)
{
- return &peer->atom->addr;
+ return &peer->atom->addr;
}
static Torrent*
getExistingTorrent (tr_peerMgr * manager,
const uint8_t * hash)
{
- tr_torrent * tor = tr_torrentFindFromHash (manager->session, hash);
+ tr_torrent * tor = tr_torrentFindFromHash (manager->session, hash);
- return tor == NULL ? NULL : tor->torrentPeers;
+ return tor == NULL ? NULL : tor->torrentPeers;
}
static int
peerCompare (const void * a, const void * b)
{
- return tr_address_compare (tr_peerAddress (a), tr_peerAddress (b));
+ return tr_address_compare (tr_peerAddress (a), tr_peerAddress (b));
}
static struct peer_atom*
getExistingAtom (const Torrent * t,
const tr_address * addr)
{
- Torrent * tt = (Torrent*)t;
- return tr_ptrArrayFindSorted (&tt->pool, addr, comparePeerAtomToAddress);
+ Torrent * tt = (Torrent*)t;
+ return tr_ptrArrayFindSorted (&tt->pool, addr, comparePeerAtomToAddress);
}
static bool
peerIsInUse (const Torrent * ct, const struct peer_atom * atom)
{
- Torrent * t = (Torrent*) ct;
+ Torrent * t = (Torrent*) ct;
- assert (torrentIsLocked (t));
+ assert (torrentIsLocked (t));
- return (atom->peer != NULL)
- || getExistingHandshake (&t->outgoingHandshakes, &atom->addr)
- || getExistingHandshake (&t->manager->incomingHandshakes, &atom->addr);
+ return (atom->peer != NULL)
+ || getExistingHandshake (&t->outgoingHandshakes, &atom->addr)
+ || getExistingHandshake (&t->manager->incomingHandshakes, &atom->addr);
}
void
tr_peerConstruct (tr_peer * peer)
{
- memset (peer, 0, sizeof (tr_peer));
+ memset (peer, 0, sizeof (tr_peer));
- peer->have = TR_BITFIELD_INIT;
+ peer->have = TR_BITFIELD_INIT;
}
static tr_peer*
peerNew (struct peer_atom * atom)
{
- tr_peer * peer = tr_new (tr_peer, 1);
- tr_peerConstruct (peer);
+ tr_peer * peer = tr_new (tr_peer, 1);
+ tr_peerConstruct (peer);
- peer->atom = atom;
- atom->peer = peer;
+ peer->atom = atom;
+ atom->peer = peer;
- return peer;
+ return peer;
}
static tr_peer*
getPeer (Torrent * torrent, struct peer_atom * atom)
{
- tr_peer * peer;
+ tr_peer * peer;
- assert (torrentIsLocked (torrent));
+ assert (torrentIsLocked (torrent));
- peer = atom->peer;
+ peer = atom->peer;
- if (peer == NULL)
+ if (peer == NULL)
{
- peer = peerNew (atom);
- tr_bitfieldConstruct (&peer->have, torrent->tor->info.pieceCount);
- tr_bitfieldConstruct (&peer->blame, torrent->tor->blockCount);
- tr_ptrArrayInsertSorted (&torrent->peers, peer, peerCompare);
+ peer = peerNew (atom);
+ tr_bitfieldConstruct (&peer->have, torrent->tor->info.pieceCount);
+ tr_bitfieldConstruct (&peer->blame, torrent->tor->blockCount);
+ tr_ptrArrayInsertSorted (&torrent->peers, peer, peerCompare);
}
- return peer;
+ return peer;
}
static void peerDeclinedAllRequests (Torrent *, const tr_peer *);
void
tr_peerDestruct (tr_torrent * tor, tr_peer * peer)
{
- assert (peer != NULL);
+ assert (peer != NULL);
- peerDeclinedAllRequests (tor->torrentPeers, peer);
+ peerDeclinedAllRequests (tor->torrentPeers, peer);
- if (peer->msgs != NULL)
- tr_peerMsgsFree (peer->msgs);
+ if (peer->msgs != NULL)
+ tr_peerMsgsFree (peer->msgs);
- if (peer->io) {
- tr_peerIoClear (peer->io);
- tr_peerIoUnref (peer->io); /* balanced by the ref in handshakeDoneCB () */
+ if (peer->io)
+ {
+ tr_peerIoClear (peer->io);
+ tr_peerIoUnref (peer->io); /* balanced by the ref in handshakeDoneCB () */
}
- tr_bitfieldDestruct (&peer->have);
- tr_bitfieldDestruct (&peer->blame);
+ tr_bitfieldDestruct (&peer->have);
+ tr_bitfieldDestruct (&peer->blame);
- if (peer->atom)
- peer->atom->peer = NULL;
+ if (peer->atom)
+ peer->atom->peer = NULL;
}
static void
peerDelete (Torrent * t, tr_peer * peer)
{
- tr_peerDestruct (t->tor, peer);
- tr_free (peer);
+ tr_peerDestruct (t->tor, peer);
+ tr_free (peer);
}
static bool
replicationExists (const Torrent * t)
{
- return t->pieceReplication != NULL;
+ return t->pieceReplication != NULL;
}
static void
replicationFree (Torrent * t)
{
- tr_free (t->pieceReplication);
- t->pieceReplication = NULL;
- t->pieceReplicationSize = 0;
+ tr_free (t->pieceReplication);
+ t->pieceReplication = NULL;
+ t->pieceReplicationSize = 0;
}
static void
replicationNew (Torrent * t)
{
- tr_piece_index_t piece_i;
- const tr_piece_index_t piece_count = t->tor->info.pieceCount;
- tr_peer ** peers = (tr_peer**) tr_ptrArrayBase (&t->peers);
- const int peer_count = tr_ptrArraySize (&t->peers);
+ tr_piece_index_t piece_i;
+ const tr_piece_index_t piece_count = t->tor->info.pieceCount;
+ tr_peer ** peers = (tr_peer**) tr_ptrArrayBase (&t->peers);
+ const int peer_count = tr_ptrArraySize (&t->peers);
- assert (!replicationExists (t));
+ assert (!replicationExists (t));
- t->pieceReplicationSize = piece_count;
- t->pieceReplication = tr_new0 (uint16_t, piece_count);
+ t->pieceReplicationSize = piece_count;
+ t->pieceReplication = tr_new0 (uint16_t, piece_count);
- for (piece_i=0; piece_i<piece_count; ++piece_i)
+ for (piece_i=0; piece_i<piece_count; ++piece_i)
{
- int peer_i;
- uint16_t r = 0;
+ int peer_i;
+ uint16_t r = 0;
- for (peer_i=0; peer_i<peer_count; ++peer_i)
- if (tr_bitfieldHas (&peers[peer_i]->have, piece_i))
- ++r;
+ for (peer_i=0; peer_i<peer_count; ++peer_i)
+ if (tr_bitfieldHas (&peers[peer_i]->have, piece_i))
+ ++r;
- t->pieceReplication[piece_i] = r;
+ t->pieceReplication[piece_i] = r;
}
}
static void
torrentFree (void * vt)
{
- Torrent * t = vt;
+ Torrent * t = vt;
- assert (t);
- assert (!t->isRunning);
- assert (torrentIsLocked (t));
- assert (tr_ptrArrayEmpty (&t->outgoingHandshakes));
- assert (tr_ptrArrayEmpty (&t->peers));
+ assert (t);
+ assert (!t->isRunning);
+ assert (torrentIsLocked (t));
+ assert (tr_ptrArrayEmpty (&t->outgoingHandshakes));
+ assert (tr_ptrArrayEmpty (&t->peers));
- tr_ptrArrayDestruct (&t->webseeds, (PtrArrayForeachFunc)tr_webseedFree);
- tr_ptrArrayDestruct (&t->pool, (PtrArrayForeachFunc)tr_free);
- tr_ptrArrayDestruct (&t->outgoingHandshakes, NULL);
- tr_ptrArrayDestruct (&t->peers, NULL);
+ tr_ptrArrayDestruct (&t->webseeds, (PtrArrayForeachFunc)tr_webseedFree);
+ tr_ptrArrayDestruct (&t->pool, (PtrArrayForeachFunc)tr_free);
+ tr_ptrArrayDestruct (&t->outgoingHandshakes, NULL);
+ tr_ptrArrayDestruct (&t->peers, NULL);
- replicationFree (t);
+ replicationFree (t);
- tr_free (t->requests);
- tr_free (t->pieces);
- tr_free (t);
+ tr_free (t->requests);
+ tr_free (t->pieces);
+ tr_free (t);
}
static void peerCallbackFunc (tr_peer *, const tr_peer_event *, void *);
static void
rebuildWebseedArray (Torrent * t, tr_torrent * tor)
{
- unsigned int i;
- const tr_info * inf = &tor->info;
+ unsigned int i;
+ const tr_info * inf = &tor->info;
- /* clear the array */
- tr_ptrArrayDestruct (&t->webseeds, (PtrArrayForeachFunc)tr_webseedFree);
- t->webseeds = TR_PTR_ARRAY_INIT;
+ /* clear the array */
+ tr_ptrArrayDestruct (&t->webseeds, (PtrArrayForeachFunc)tr_webseedFree);
+ t->webseeds = TR_PTR_ARRAY_INIT;
- /* repopulate it */
- for (i = 0; i < inf->webseedCount; ++i)
+ /* repopulate it */
+ for (i = 0; i < inf->webseedCount; ++i)
{
- tr_webseed * w = tr_webseedNew (tor, inf->webseeds[i], peerCallbackFunc, t);
- tr_ptrArrayAppend (&t->webseeds, w);
+ tr_webseed * w = tr_webseedNew (tor, inf->webseeds[i], peerCallbackFunc, t);
+ tr_ptrArrayAppend (&t->webseeds, w);
}
}
static Torrent*
torrentNew (tr_peerMgr * manager, tr_torrent * tor)
{
- Torrent * t;
+ Torrent * t;
- t = tr_new0 (Torrent, 1);
- t->manager = manager;
- t->tor = tor;
- t->pool = TR_PTR_ARRAY_INIT;
- t->peers = TR_PTR_ARRAY_INIT;
- t->webseeds = TR_PTR_ARRAY_INIT;
- t->outgoingHandshakes = TR_PTR_ARRAY_INIT;
+ t = tr_new0 (Torrent, 1);
+ t->manager = manager;
+ t->tor = tor;
+ t->pool = TR_PTR_ARRAY_INIT;
+ t->peers = TR_PTR_ARRAY_INIT;
+ t->webseeds = TR_PTR_ARRAY_INIT;
+ t->outgoingHandshakes = TR_PTR_ARRAY_INIT;
- rebuildWebseedArray (t, tor);
+ rebuildWebseedArray (t, tor);
- return t;
+ return t;
}
static void ensureMgrTimersExist (struct tr_peerMgr * m);
tr_peerMgr*
tr_peerMgrNew (tr_session * session)
{
- tr_peerMgr * m = tr_new0 (tr_peerMgr, 1);
- m->session = session;
- m->incomingHandshakes = TR_PTR_ARRAY_INIT;
- ensureMgrTimersExist (m);
- return m;
+ tr_peerMgr * m = tr_new0 (tr_peerMgr, 1);
+ m->session = session;
+ m->incomingHandshakes = TR_PTR_ARRAY_INIT;
+ ensureMgrTimersExist (m);
+ return m;
}
static void
deleteTimer (struct event ** t)
{
- if (*t != NULL)
+ if (*t != NULL)
{
- event_free (*t);
- *t = NULL;
+ event_free (*t);
+ *t = NULL;
}
}
static void
deleteTimers (struct tr_peerMgr * m)
{
- deleteTimer (&m->atomTimer);
- deleteTimer (&m->bandwidthTimer);
- deleteTimer (&m->rechokeTimer);
- deleteTimer (&m->refillUpkeepTimer);
+ deleteTimer (&m->atomTimer);
+ deleteTimer (&m->bandwidthTimer);
+ deleteTimer (&m->rechokeTimer);
+ deleteTimer (&m->refillUpkeepTimer);
}
void
tr_peerMgrFree (tr_peerMgr * manager)
{
- managerLock (manager);
+ managerLock (manager);
- deleteTimers (manager);
+ deleteTimers (manager);
- /* free the handshakes. Abort invokes handshakeDoneCB (), which removes
- * the item from manager->handshakes, so this is a little roundabout... */
- while (!tr_ptrArrayEmpty (&manager->incomingHandshakes))
- tr_handshakeAbort (tr_ptrArrayNth (&manager->incomingHandshakes, 0));
+ /* free the handshakes. Abort invokes handshakeDoneCB (), which removes
+ * the item from manager->handshakes, so this is a little roundabout... */
+ while (!tr_ptrArrayEmpty (&manager->incomingHandshakes))
+ tr_handshakeAbort (tr_ptrArrayNth (&manager->incomingHandshakes, 0));
- tr_ptrArrayDestruct (&manager->incomingHandshakes, NULL);
+ tr_ptrArrayDestruct (&manager->incomingHandshakes, NULL);
- managerUnlock (manager);
- tr_free (manager);
+ managerUnlock (manager);
+ tr_free (manager);
}
static int
clientIsDownloadingFrom (const tr_torrent * tor, const tr_peer * peer)
{
- if (!tr_torrentHasMetadata (tor))
- return true;
+ if (!tr_torrentHasMetadata (tor))
+ return true;
- return peer->clientIsInterested && !peer->clientIsChoked;
+ return peer->clientIsInterested && !peer->clientIsChoked;
}
static int
clientIsUploadingTo (const tr_peer * peer)
{
- return peer->peerIsInterested && !peer->peerIsChoked;
+ return peer->peerIsInterested && !peer->peerIsChoked;
}
/***
void
tr_peerMgrOnBlocklistChanged (tr_peerMgr * mgr)
{
- tr_torrent * tor = NULL;
- tr_session * session = mgr->session;
+ tr_torrent * tor = NULL;
+ tr_session * session = mgr->session;
- /* we cache whether or not a peer is blocklisted...
- since the blocklist has changed, erase that cached value */
- while ((tor = tr_torrentNext (session, tor)))
+ /* we cache whether or not a peer is blocklisted...
+ since the blocklist has changed, erase that cached value */
+ while ((tor = tr_torrentNext (session, tor)))
{
- int i;
- Torrent * t = tor->torrentPeers;
- const int n = tr_ptrArraySize (&t->pool);
- for (i=0; i<n; ++i) {
- struct peer_atom * atom = tr_ptrArrayNth (&t->pool, i);
- atom->blocklisted = -1;
+ int i;
+ Torrent * t = tor->torrentPeers;
+ const int n = tr_ptrArraySize (&t->pool);
+ for (i=0; i<n; ++i)
+ {
+ struct peer_atom * atom = tr_ptrArrayNth (&t->pool, i);
+ atom->blocklisted = -1;
}
}
}
static bool
isAtomBlocklisted (tr_session * session, struct peer_atom * atom)
{
- if (atom->blocklisted < 0)
- atom->blocklisted = tr_sessionIsAddressBlocked (session, &atom->addr);
+ if (atom->blocklisted < 0)
+ atom->blocklisted = tr_sessionIsAddressBlocked (session, &atom->addr);
- assert (tr_isBool (atom->blocklisted));
- return atom->blocklisted;
+ assert (tr_isBool (atom->blocklisted));
+ return atom->blocklisted;
}
static void
atomSetSeedProbability (struct peer_atom * atom, int seedProbability)
{
- assert (atom != NULL);
- assert (-1<=seedProbability && seedProbability<=100);
+ assert (atom != NULL);
+ assert (-1<=seedProbability && seedProbability<=100);
- atom->seedProbability = seedProbability;
+ atom->seedProbability = seedProbability;
- if (seedProbability == 100)
- atom->flags |= ADDED_F_SEED_FLAG;
- else if (seedProbability != -1)
- atom->flags &= ~ADDED_F_SEED_FLAG;
+ if (seedProbability == 100)
+ atom->flags |= ADDED_F_SEED_FLAG;
+ else if (seedProbability != -1)
+ atom->flags &= ~ADDED_F_SEED_FLAG;
}
static inline bool
atomIsSeed (const struct peer_atom * atom)
{
- return atom->seedProbability == 100;
+ return atom->seedProbability == 100;
}
static void
atomSetSeed (const Torrent * t, struct peer_atom * atom)
{
- if (!atomIsSeed (atom))
+ if (!atomIsSeed (atom))
{
- tordbg (t, "marking peer %s as a seed", tr_atomAddrStr (atom));
+ tordbg (t, "marking peer %s as a seed", tr_atomAddrStr (atom));
- atomSetSeedProbability (atom, 100);
+ atomSetSeedProbability (atom, 100);
}
}
tr_peerMgrPeerIsSeed (const tr_torrent * tor,
const tr_address * addr)
{
- bool isSeed = false;
- const Torrent * t = tor->torrentPeers;
- const struct peer_atom * atom = getExistingAtom (t, addr);
+ bool isSeed = false;
+ const Torrent * t = tor->torrentPeers;
+ const struct peer_atom * atom = getExistingAtom (t, addr);
- if (atom)
- isSeed = atomIsSeed (atom);
+ if (atom)
+ isSeed = atomIsSeed (atom);
- return isSeed;
+ return isSeed;
}
void
tr_peerMgrSetUtpSupported (tr_torrent * tor, const tr_address * addr)
{
- struct peer_atom * atom = getExistingAtom (tor->torrentPeers, addr);
+ struct peer_atom * atom = getExistingAtom (tor->torrentPeers, addr);
- if (atom)
- atom->flags |= ADDED_F_UTP_FLAGS;
+ if (atom)
+ atom->flags |= ADDED_F_UTP_FLAGS;
}
void
tr_peerMgrSetUtpFailed (tr_torrent *tor, const tr_address *addr, bool failed)
{
- struct peer_atom * atom = getExistingAtom (tor->torrentPeers, addr);
+ struct peer_atom * atom = getExistingAtom (tor->torrentPeers, addr);
- if (atom)
- atom->utp_failed = failed;
+ if (atom)
+ atom->utp_failed = failed;
}
struct tr_shared
{
- bool isEnabled;
- bool isShuttingDown;
- bool doPortCheck;
+ bool isEnabled;
+ bool isShuttingDown;
+ bool doPortCheck;
- tr_port_forwarding natpmpStatus;
- tr_port_forwarding upnpStatus;
+ tr_port_forwarding natpmpStatus;
+ tr_port_forwarding upnpStatus;
- tr_upnp * upnp;
- tr_natpmp * natpmp;
- tr_session * session;
+ tr_upnp * upnp;
+ tr_natpmp * natpmp;
+ tr_session * session;
- struct event * timer;
+ struct event * timer;
};
/***
static const char*
getNatStateStr (int state)
{
- switch (state)
+ switch (state)
{
- case TR_PORT_MAPPING: return _("Starting");
- case TR_PORT_MAPPED: return _("Forwarded");
- case TR_PORT_UNMAPPING: return _("Stopping");
- case TR_PORT_UNMAPPED: return _("Not forwarded");
- default: return "???";
+ case TR_PORT_MAPPING: return _("Starting");
+ case TR_PORT_MAPPED: return _("Forwarded");
+ case TR_PORT_UNMAPPING: return _("Stopping");
+ case TR_PORT_UNMAPPED: return _("Not forwarded");
+ default: return "???";
}
}
static void
natPulse (tr_shared * s, bool do_check)
{
- const tr_port private_peer_port = s->session->private_peer_port;
- const int is_enabled = s->isEnabled && !s->isShuttingDown;
- tr_port public_peer_port;
- int oldStatus;
- int newStatus;
+ int oldStatus;
+ int newStatus;
+ tr_port public_peer_port;
+ const tr_port private_peer_port = s->session->private_peer_port;
+ const int is_enabled = s->isEnabled && !s->isShuttingDown;
- if (s->natpmp == NULL)
- s->natpmp = tr_natpmpInit ();
- if (s->upnp == NULL)
- s->upnp = tr_upnpInit ();
+ if (s->natpmp == NULL)
+ s->natpmp = tr_natpmpInit ();
- oldStatus = tr_sharedTraversalStatus (s);
+ if (s->upnp == NULL)
+ s->upnp = tr_upnpInit ();
- s->natpmpStatus = tr_natpmpPulse (s->natpmp, private_peer_port, is_enabled, &public_peer_port);
- if (s->natpmpStatus == TR_PORT_MAPPED)
- s->session->public_peer_port = public_peer_port;
+ oldStatus = tr_sharedTraversalStatus (s);
- s->upnpStatus = tr_upnpPulse (s->upnp, private_peer_port, is_enabled, do_check);
+ s->natpmpStatus = tr_natpmpPulse (s->natpmp, private_peer_port, is_enabled, &public_peer_port);
+ if (s->natpmpStatus == TR_PORT_MAPPED)
+ s->session->public_peer_port = public_peer_port;
- newStatus = tr_sharedTraversalStatus (s);
+ s->upnpStatus = tr_upnpPulse (s->upnp, private_peer_port, is_enabled, do_check);
- if (newStatus != oldStatus)
- tr_ninf (getKey (), _("State changed from \"%1$s\" to \"%2$s\""),
- getNatStateStr (oldStatus),
- getNatStateStr (newStatus));
+ newStatus = tr_sharedTraversalStatus (s);
+
+ if (newStatus != oldStatus)
+ tr_ninf (getKey (), _("State changed from \"%1$s\" to \"%2$s\""),
+ getNatStateStr (oldStatus),
+ getNatStateStr (newStatus));
}
static void
set_evtimer_from_status (tr_shared * s)
{
- int sec=0, msec=0;
+ int sec=0, msec=0;
- /* when to wake up again */
- switch (tr_sharedTraversalStatus (s))
+ /* when to wake up again */
+ switch (tr_sharedTraversalStatus (s))
{
- case TR_PORT_MAPPED:
- /* if we're mapped, everything is fine... check back in 20 minutes
- * to renew the port forwarding if it's expired */
- s->doPortCheck = true;
- sec = 60 * 20;
- break;
-
- case TR_PORT_ERROR:
- /* some kind of an error. wait 60 seconds and retry */
- sec = 60;
- break;
-
- default:
- /* in progress. pulse frequently. */
- msec = 333000;
- break;
+ case TR_PORT_MAPPED:
+ /* if we're mapped, everything is fine... check back in 20 minutes
+ * to renew the port forwarding if it's expired */
+ s->doPortCheck = true;
+ sec = 60 * 20;
+ break;
+
+ case TR_PORT_ERROR:
+ /* some kind of an error. wait 60 seconds and retry */
+ sec = 60;
+ break;
+
+ default:
+ /* in progress. pulse frequently. */
+ msec = 333000;
+ break;
}
- if (s->timer != NULL)
- tr_timerAdd (s->timer, sec, msec);
+ if (s->timer != NULL)
+ tr_timerAdd (s->timer, sec, msec);
}
static void
onTimer (int fd UNUSED, short what UNUSED, void * vshared)
{
- tr_shared * s = vshared;
+ tr_shared * s = vshared;
- assert (s);
- assert (s->timer);
+ assert (s);
+ assert (s->timer);
- /* do something */
- natPulse (s, s->doPortCheck);
- s->doPortCheck = false;
+ /* do something */
+ natPulse (s, s->doPortCheck);
+ s->doPortCheck = false;
- /* set up the timer for the next pulse */
- set_evtimer_from_status (s);
+ /* set up the timer for the next pulse */
+ set_evtimer_from_status (s);
}
/***
tr_shared *
tr_sharedInit (tr_session * session)
{
- tr_shared * s = tr_new0 (tr_shared, 1);
+ tr_shared * s = tr_new0 (tr_shared, 1);
- s->session = session;
- s->isEnabled = false;
- s->upnpStatus = TR_PORT_UNMAPPED;
- s->natpmpStatus = TR_PORT_UNMAPPED;
+ s->session = session;
+ s->isEnabled = false;
+ s->upnpStatus = TR_PORT_UNMAPPED;
+ s->natpmpStatus = TR_PORT_UNMAPPED;
#if 0
- if (isEnabled)
+ if (isEnabled)
{
- s->timer = tr_new0 (struct event, 1);
- evtimer_set (s->timer, onTimer, s);
- tr_timerAdd (s->timer, 0, 333000);
+ s->timer = tr_new0 (struct event, 1);
+ evtimer_set (s->timer, onTimer, s);
+ tr_timerAdd (s->timer, 0, 333000);
}
#endif
- return s;
+ return s;
}
static void
stop_timer (tr_shared * s)
{
- if (s->timer != NULL)
+ if (s->timer != NULL)
{
- event_free (s->timer);
- s->timer = NULL;
+ event_free (s->timer);
+ s->timer = NULL;
}
}
static void
stop_forwarding (tr_shared * s)
{
- tr_ninf (getKey (), "%s", _("Stopped"));
- natPulse (s, false);
+ tr_ninf (getKey (), "%s", _("Stopped"));
+ natPulse (s, false);
- tr_natpmpClose (s->natpmp);
- s->natpmp = NULL;
- s->natpmpStatus = TR_PORT_UNMAPPED;
+ tr_natpmpClose (s->natpmp);
+ s->natpmp = NULL;
+ s->natpmpStatus = TR_PORT_UNMAPPED;
- tr_upnpClose (s->upnp);
- s->upnp = NULL;
- s->upnpStatus = TR_PORT_UNMAPPED;
+ tr_upnpClose (s->upnp);
+ s->upnp = NULL;
+ s->upnpStatus = TR_PORT_UNMAPPED;
- stop_timer (s);
+ stop_timer (s);
}
void
tr_sharedClose (tr_session * session)
{
- tr_shared * s = session->shared;
+ tr_shared * s = session->shared;
- s->isShuttingDown = true;
- stop_forwarding (s);
- s->session->shared = NULL;
- tr_free (s);
+ s->isShuttingDown = true;
+ stop_forwarding (s);
+ s->session->shared = NULL;
+ tr_free (s);
}
static void
start_timer (tr_shared * s)
{
- s->timer = evtimer_new (s->session->event_base, onTimer, s);
- set_evtimer_from_status (s);
+ s->timer = evtimer_new (s->session->event_base, onTimer, s);
+ set_evtimer_from_status (s);
}
void
tr_sharedTraversalEnable (tr_shared * s, bool isEnabled)
{
- if ((s->isEnabled = isEnabled))
- start_timer (s);
- else
- stop_forwarding (s);
+ if ((s->isEnabled = isEnabled))
+ start_timer (s);
+ else
+ stop_forwarding (s);
}
void
tr_sharedPortChanged (tr_session * session)
{
- tr_shared * s = session->shared;
+ tr_shared * s = session->shared;
- if (s->isEnabled)
+ if (s->isEnabled)
{
- stop_timer (s);
- natPulse (s, false);
- start_timer (s);
+ stop_timer (s);
+ natPulse (s, false);
+ start_timer (s);
}
}
bool
tr_sharedTraversalIsEnabled (const tr_shared * s)
{
- return s->isEnabled;
+ return s->isEnabled;
}
int
tr_sharedTraversalStatus (const tr_shared * s)
{
- return MAX (s->natpmpStatus, s->upnpStatus);
+ return MAX (s->natpmpStatus, s->upnpStatus);
}
static int messageQueueCount = 0;
#ifndef WIN32
- /* make null versions of these win32 functions */
- static inline int IsDebuggerPresent (void) { return false; }
- static inline void OutputDebugString (const void * unused UNUSED) { }
+ /* make null versions of these win32 functions */
+ static inline int IsDebuggerPresent (void) { return false; }
+ static inline void OutputDebugString (const void * unused UNUSED) { }
#endif
/***
static tr_lock*
getMessageLock (void)
{
- static tr_lock * l = NULL;
+ static tr_lock * l = NULL;
- if (!l)
- l = tr_lockNew ();
+ if (!l)
+ l = tr_lockNew ();
- return l;
+ return l;
}
void*
tr_getLog (void)
{
- static bool initialized = false;
- static FILE * file = NULL;
+ static bool initialized = false;
+ static FILE * file = NULL;
- if (!initialized)
+ if (!initialized)
{
- const char * str = getenv ("TR_DEBUG_FD");
- int fd = 0;
- if (str && *str)
- fd = atoi (str);
- switch (fd)
+ int fd = 0;
+ const char * str = getenv ("TR_DEBUG_FD");
+
+ if (str && *str)
+ fd = atoi (str);
+
+ switch (fd)
{
- case 1:
- file = stdout; break;
+ case 1:
+ file = stdout;
+ break;
- case 2:
- file = stderr; break;
+ case 2:
+ file = stderr;
+ break;
- default:
- file = NULL; break;
+ default:
+ file = NULL;
+ break;
}
- initialized = true;
+
+ initialized = true;
}
- return file;
+ return file;
}
void
void
tr_setMessageQueuing (bool enabled)
{
- messageQueuing = enabled;
+ messageQueuing = enabled;
}
bool
tr_getMessageQueuing (void)
{
- return messageQueuing != 0;
+ return messageQueuing != 0;
}
tr_msg_list *
tr_getQueuedMessages (void)
{
- tr_msg_list * ret;
- tr_lockLock (getMessageLock ());
+ tr_msg_list * ret;
+ tr_lockLock (getMessageLock ());
- ret = messageQueue;
- messageQueue = NULL;
- messageQueueTail = &messageQueue;
+ ret = messageQueue;
+ messageQueue = NULL;
+ messageQueueTail = &messageQueue;
- messageQueueCount = 0;
+ messageQueueCount = 0;
- tr_lockUnlock (getMessageLock ());
- return ret;
+ tr_lockUnlock (getMessageLock ());
+ return ret;
}
void
tr_freeMessageList (tr_msg_list * list)
{
- tr_msg_list * next;
+ tr_msg_list * next;
- while (NULL != list)
+ while (NULL != list)
{
- next = list->next;
- free (list->message);
- free (list->name);
- free (list);
- list = next;
+ next = list->next;
+ free (list->message);
+ free (list->name);
+ free (list);
+ list = next;
}
}
tr_localtime_r (const time_t *_clock, struct tm *_result)
{
#ifdef HAVE_LOCALTIME_R
- return localtime_r (_clock, _result);
+ return localtime_r (_clock, _result);
#else
- struct tm *p = localtime (_clock);
- if (p)
- * (_result) = *p;
- return p;
+ struct tm *p = localtime (_clock);
+ if (p)
+ * (_result) = *p;
+ return p;
#endif
}
char*
tr_getLogTimeStr (char * buf, int buflen)
{
- char tmp[64];
- struct tm now_tm;
- struct timeval tv;
- time_t seconds;
- int milliseconds;
+ char tmp[64];
+ struct tm now_tm;
+ struct timeval tv;
+ time_t seconds;
+ int milliseconds;
- gettimeofday (&tv, NULL);
+ gettimeofday (&tv, NULL);
- seconds = tv.tv_sec;
- tr_localtime_r (&seconds, &now_tm);
- strftime (tmp, sizeof (tmp), "%H:%M:%S", &now_tm);
- milliseconds = tv.tv_usec / 1000;
- tr_snprintf (buf, buflen, "%s.%03d", tmp, milliseconds);
+ seconds = tv.tv_sec;
+ tr_localtime_r (&seconds, &now_tm);
+ strftime (tmp, sizeof (tmp), "%H:%M:%S", &now_tm);
+ milliseconds = tv.tv_usec / 1000;
+ tr_snprintf (buf, buflen, "%s.%03d", tmp, milliseconds);
- return buf;
+ return buf;
}
bool
tr_deepLoggingIsActive (void)
{
- static int8_t deepLoggingIsActive = -1;
+ static int8_t deepLoggingIsActive = -1;
- if (deepLoggingIsActive < 0)
- deepLoggingIsActive = IsDebuggerPresent () || (tr_getLog ()!=NULL);
+ if (deepLoggingIsActive < 0)
+ deepLoggingIsActive = IsDebuggerPresent () || (tr_getLog ()!=NULL);
- return deepLoggingIsActive != 0;
+ return deepLoggingIsActive != 0;
}
void
const char * fmt,
...)
{
- FILE * fp = tr_getLog ();
- if (fp || IsDebuggerPresent ())
+ FILE * fp = tr_getLog ();
+ if (fp || IsDebuggerPresent ())
{
- va_list args;
- char timestr[64];
- struct evbuffer * buf = evbuffer_new ();
- char * base = tr_basename (file);
- char * message;
-
- evbuffer_add_printf (buf, "[%s] ",
- tr_getLogTimeStr (timestr, sizeof (timestr)));
- if (name)
- evbuffer_add_printf (buf, "%s ", name);
- va_start (args, fmt);
- evbuffer_add_vprintf (buf, fmt, args);
- va_end (args);
- evbuffer_add_printf (buf, " (%s:%d)\n", base, line);
- /* FIXME (libevent2) ifdef this out for nonwindows platforms */
- message = evbuffer_free_to_str (buf);
- OutputDebugString (message);
- if (fp)
- fputs (message, fp);
-
- tr_free (message);
- tr_free (base);
+ va_list args;
+ char timestr[64];
+ char * message;
+ struct evbuffer * buf = evbuffer_new ();
+ char * base = tr_basename (file);
+
+ evbuffer_add_printf (buf, "[%s] ",
+ tr_getLogTimeStr (timestr, sizeof (timestr)));
+ if (name)
+ evbuffer_add_printf (buf, "%s ", name);
+ va_start (args, fmt);
+ evbuffer_add_vprintf (buf, fmt, args);
+ va_end (args);
+ evbuffer_add_printf (buf, " (%s:%d)\n", base, line);
+ /* FIXME (libevent2) ifdef this out for nonwindows platforms */
+ message = evbuffer_free_to_str (buf);
+ OutputDebugString (message);
+ if (fp)
+ fputs (message, fp);
+
+ tr_free (message);
+ tr_free (base);
}
}
const char * name,
const char * fmt, ...)
{
- const int err = errno; /* message logging shouldn't affect errno */
- char buf[1024];
- va_list ap;
- tr_lockLock (getMessageLock ());
+ const int err = errno; /* message logging shouldn't affect errno */
+ char buf[1024];
+ va_list ap;
+ tr_lockLock (getMessageLock ());
- /* build the text message */
- *buf = '\0';
- va_start (ap, fmt);
- evutil_vsnprintf (buf, sizeof (buf), fmt, ap);
- va_end (ap);
+ /* build the text message */
+ *buf = '\0';
+ va_start (ap, fmt);
+ evutil_vsnprintf (buf, sizeof (buf), fmt, ap);
+ va_end (ap);
- OutputDebugString (buf);
+ OutputDebugString (buf);
- if (*buf)
+ if (*buf)
{
- if (messageQueuing)
+ if (messageQueuing)
{
- tr_msg_list * newmsg;
- newmsg = tr_new0 (tr_msg_list, 1);
- newmsg->level = level;
- newmsg->when = tr_time ();
- newmsg->message = tr_strdup (buf);
- newmsg->file = file;
- newmsg->line = line;
- newmsg->name = tr_strdup (name);
-
- *messageQueueTail = newmsg;
- messageQueueTail = &newmsg->next;
- ++messageQueueCount;
-
- if (messageQueueCount > TR_MAX_MSG_LOG)
+ tr_msg_list * newmsg;
+ newmsg = tr_new0 (tr_msg_list, 1);
+ newmsg->level = level;
+ newmsg->when = tr_time ();
+ newmsg->message = tr_strdup (buf);
+ newmsg->file = file;
+ newmsg->line = line;
+ newmsg->name = tr_strdup (name);
+
+ *messageQueueTail = newmsg;
+ messageQueueTail = &newmsg->next;
+ ++messageQueueCount;
+
+ if (messageQueueCount > TR_MAX_MSG_LOG)
{
- tr_msg_list * old = messageQueue;
- messageQueue = old->next;
- old->next = NULL;
- tr_freeMessageList (old);
-
- --messageQueueCount;
-
- assert (messageQueueCount == TR_MAX_MSG_LOG);
+ tr_msg_list * old = messageQueue;
+ messageQueue = old->next;
+ old->next = NULL;
+ tr_freeMessageList (old);
+ --messageQueueCount;
+ assert (messageQueueCount == TR_MAX_MSG_LOG);
}
}
- else
+ else
{
- char timestr[64];
- FILE * fp;
+ FILE * fp;
+ char timestr[64];
- fp = tr_getLog ();
- if (fp == NULL)
- fp = stderr;
+ fp = tr_getLog ();
+ if (fp == NULL)
+ fp = stderr;
- tr_getLogTimeStr (timestr, sizeof (timestr));
+ tr_getLogTimeStr (timestr, sizeof (timestr));
- if (name)
- fprintf (fp, "[%s] %s: %s\n", timestr, name, buf);
- else
- fprintf (fp, "[%s] %s\n", timestr, buf);
- fflush (fp);
+ if (name)
+ fprintf (fp, "[%s] %s: %s\n", timestr, name, buf);
+ else
+ fprintf (fp, "[%s] %s\n", timestr, buf);
+ fflush (fp);
}
}
- tr_lockUnlock (getMessageLock ());
- errno = err;
+ tr_lockUnlock (getMessageLock ());
+ errno = err;
}
/***
void*
tr_malloc (size_t size)
{
- return size ? malloc (size) : NULL;
+ return size ? malloc (size) : NULL;
}
void*
tr_malloc0 (size_t size)
{
- return size ? calloc (1, size) : NULL;
+ return size ? calloc (1, size) : NULL;
}
void
tr_free (void * p)
{
- if (p != NULL)
- free (p);
+ if (p != NULL)
+ free (p);
}
void*
tr_memdup (const void * src, size_t byteCount)
{
- return memcpy (tr_malloc (byteCount), src, byteCount);
+ return memcpy (tr_malloc (byteCount), src, byteCount);
}
/***
const char*
tr_strip_positional_args (const char* str)
{
- const char * in = str;
- static size_t bufsize = 0;
- static char * buf = NULL;
- const size_t len = str ? strlen (str) : 0;
- char * out;
+ char * out;
+ static size_t bufsize = 0;
+ static char * buf = NULL;
+ const char * in = str;
+ const size_t len = str ? strlen (str) : 0;
- if (!buf || (bufsize < len))
+ if (!buf || (bufsize < len))
{
- bufsize = len * 2 + 1;
- buf = tr_renew (char, buf, bufsize);
+ bufsize = len * 2 + 1;
+ buf = tr_renew (char, buf, bufsize);
}
- for (out = buf; str && *str; ++str)
+ for (out = buf; str && *str; ++str)
{
- *out++ = *str;
+ *out++ = *str;
- if ((*str == '%') && isdigit (str[1]))
+ if ((*str == '%') && isdigit (str[1]))
{
- const char * tmp = str + 1;
- while (isdigit (*tmp))
- ++tmp;
- if (*tmp == '$')
- str = tmp[1]=='\'' ? tmp+1 : tmp;
+ const char * tmp = str + 1;
+ while (isdigit (*tmp))
+ ++tmp;
+ if (*tmp == '$')
+ str = tmp[1]=='\'' ? tmp+1 : tmp;
}
- if ((*str == '%') && (str[1] == '\''))
- str = str + 1;
+ if ((*str == '%') && (str[1] == '\''))
+ str = str + 1;
}
- *out = '\0';
- return !in || strcmp (buf, in) ? buf : in;
+ *out = '\0';
+ return !in || strcmp (buf, in) ? buf : in;
}
/**
void
tr_timerAdd (struct event * timer, int seconds, int microseconds)
{
- struct timeval tv;
- tv.tv_sec = seconds;
- tv.tv_usec = microseconds;
+ struct timeval tv;
+ tv.tv_sec = seconds;
+ tv.tv_usec = microseconds;
- assert (tv.tv_sec >= 0);
- assert (tv.tv_usec >= 0);
- assert (tv.tv_usec < 1000000);
+ assert (tv.tv_sec >= 0);
+ assert (tv.tv_usec >= 0);
+ assert (tv.tv_usec < 1000000);
- evtimer_add (timer, &tv);
+ evtimer_add (timer, &tv);
}
void
tr_timerAddMsec (struct event * timer, int msec)
{
- const int seconds = msec / 1000;
- const int usec = (msec%1000) * 1000;
- tr_timerAdd (timer, seconds, usec);
+ const int seconds = msec / 1000;
+ const int usec = (msec%1000) * 1000;
+ tr_timerAdd (timer, seconds, usec);
}
/**
uint8_t *
tr_loadFile (const char * path,
- size_t * size)
+ size_t * size)
{
- uint8_t * buf;
- struct stat sb;
- int fd;
- ssize_t n;
- const char * const err_fmt = _("Couldn't read \"%1$s\": %2$s");
+ uint8_t * buf;
+ struct stat sb;
+ int fd;
+ ssize_t n;
+ const char * const err_fmt = _("Couldn't read \"%1$s\": %2$s");
- /* try to stat the file */
- errno = 0;
- if (stat (path, &sb))
+ /* try to stat the file */
+ errno = 0;
+ if (stat (path, &sb))
{
- const int err = errno;
- tr_dbg (err_fmt, path, tr_strerror (errno));
- errno = err;
- return NULL;
+ const int err = errno;
+ tr_dbg (err_fmt, path, tr_strerror (errno));
+ errno = err;
+ return NULL;
}
- if ((sb.st_mode & S_IFMT) != S_IFREG)
+ if ((sb.st_mode & S_IFMT) != S_IFREG)
{
- tr_err (err_fmt, path, _("Not a regular file"));
- errno = EISDIR;
- return NULL;
+ tr_err (err_fmt, path, _("Not a regular file"));
+ errno = EISDIR;
+ return NULL;
}
- /* Load the torrent file into our buffer */
- fd = tr_open_file_for_scanning (path);
- if (fd < 0)
+ /* Load the torrent file into our buffer */
+ fd = tr_open_file_for_scanning (path);
+ if (fd < 0)
{
- const int err = errno;
- tr_err (err_fmt, path, tr_strerror (errno));
- errno = err;
- return NULL;
+ const int err = errno;
+ tr_err (err_fmt, path, tr_strerror (errno));
+ errno = err;
+ return NULL;
}
- buf = tr_malloc (sb.st_size + 1);
- if (!buf)
+ buf = tr_malloc (sb.st_size + 1);
+ if (!buf)
{
- const int err = errno;
- tr_err (err_fmt, path, _("Memory allocation failed"));
- tr_close_file (fd);
- errno = err;
- return NULL;
+ const int err = errno;
+ tr_err (err_fmt, path, _("Memory allocation failed"));
+ tr_close_file (fd);
+ errno = err;
+ return NULL;
}
- n = read (fd, buf, (size_t)sb.st_size);
- if (n == -1)
+ n = read (fd, buf, (size_t)sb.st_size);
+ if (n == -1)
{
- const int err = errno;
- tr_err (err_fmt, path, tr_strerror (errno));
- tr_close_file (fd);
- free (buf);
- errno = err;
- return NULL;
+ const int err = errno;
+ tr_err (err_fmt, path, tr_strerror (errno));
+ tr_close_file (fd);
+ free (buf);
+ errno = err;
+ return NULL;
}
- tr_close_file (fd);
- buf[ sb.st_size ] = '\0';
- *size = sb.st_size;
- return buf;
+ tr_close_file (fd);
+ buf[ sb.st_size ] = '\0';
+ *size = sb.st_size;
+ return buf;
}
char*
tr_basename (const char * path)
{
- char * tmp = tr_strdup (path);
- char * ret = tr_strdup (basename (tmp));
- tr_free (tmp);
- return ret;
+ char * tmp = tr_strdup (path);
+ char * ret = tr_strdup (basename (tmp));
+ tr_free (tmp);
+ return ret;
}
char*
tr_dirname (const char * path)
{
- char * tmp = tr_strdup (path);
- char * ret = tr_strdup (dirname (tmp));
- tr_free (tmp);
- return ret;
+ char * tmp = tr_strdup (path);
+ char * ret = tr_strdup (dirname (tmp));
+ tr_free (tmp);
+ return ret;
}
char*
tr_mkdtemp (char * template)
{
#ifdef HAVE_MKDTEMP
- return mkdtemp (template);
+ return mkdtemp (template);
#else
- if (!mktemp (template) || mkdir (template, 0700))
- return NULL;
- return template;
+ if (!mktemp (template) || mkdir (template, 0700))
+ return NULL;
+ return template;
#endif
}
tr_mkdir (const char * path, int permissions UNUSED)
{
#ifdef WIN32
- if (path && isalpha (path[0]) && path[1] == ':' && !path[2])
- return 0;
- return mkdir (path);
+ if (path && isalpha (path[0]) && path[1] == ':' && !path[2])
+ return 0;
+ return mkdir (path);
#else
- return mkdir (path, permissions);
+ return mkdir (path, permissions);
#endif
}
tr_mkdirp (const char * path_in,
int permissions)
{
- char * path = tr_strdup (path_in);
- char * p, * pp;
- struct stat sb;
- bool done;
- int tmperr;
- int rv;
-
- /* walk past the root */
- p = path;
- while (*p == TR_PATH_DELIMITER)
- ++p;
-
- pp = p;
- done = false;
- while ((p = strchr (pp, TR_PATH_DELIMITER)) || (p = strchr (pp, '\0')))
+ char * p;
+ char * pp;
+ bool done;
+ int tmperr;
+ int rv;
+ struct stat sb;
+ char * path = tr_strdup (path_in);
+
+ /* walk past the root */
+ p = path;
+ while (*p == TR_PATH_DELIMITER)
+ ++p;
+
+ pp = p;
+ done = false;
+ while ((p = strchr (pp, TR_PATH_DELIMITER)) || (p = strchr (pp, '\0')))
{
- if (!*p)
- done = true;
- else
- *p = '\0';
-
- tmperr = errno;
- rv = stat (path, &sb);
- errno = tmperr;
- if (rv)
+ if (!*p)
+ done = true;
+ else
+ *p = '\0';
+
+ tmperr = errno;
+ rv = stat (path, &sb);
+ errno = tmperr;
+ if (rv)
{
- /* Folder doesn't exist yet */
- if (tr_mkdir (path, permissions))
+ /* Folder doesn't exist yet */
+ if (tr_mkdir (path, permissions))
{
- tmperr = errno;
- tr_err (_("Couldn't create \"%1$s\": %2$s"), path, tr_strerror (tmperr));
- tr_free (path);
- errno = tmperr;
- return -1;
+ tmperr = errno;
+ tr_err (_("Couldn't create \"%1$s\": %2$s"), path, tr_strerror (tmperr));
+ tr_free (path);
+ errno = tmperr;
+ return -1;
}
}
- else if ((sb.st_mode & S_IFMT) != S_IFDIR)
+ else if ((sb.st_mode & S_IFMT) != S_IFDIR)
{
- /* Node exists but isn't a folder */
- char * buf = tr_strdup_printf (_("File \"%s\" is in the way"), path);
- tr_err (_("Couldn't create \"%1$s\": %2$s"), path_in, buf);
- tr_free (buf);
- tr_free (path);
- errno = ENOTDIR;
- return -1;
+ /* Node exists but isn't a folder */
+ char * buf = tr_strdup_printf (_("File \"%s\" is in the way"), path);
+ tr_err (_("Couldn't create \"%1$s\": %2$s"), path_in, buf);
+ tr_free (buf);
+ tr_free (path);
+ errno = ENOTDIR;
+ return -1;
}
- if (done)
- break;
+ if (done)
+ break;
- *p = TR_PATH_DELIMITER;
- p++;
- pp = p;
+ *p = TR_PATH_DELIMITER;
+ p++;
+ pp = p;
}
- tr_free (path);
- return 0;
+ tr_free (path);
+ return 0;
}
char*
tr_buildPath (const char *first_element, ...)
{
- size_t bufLen = 0;
- const char * element;
- char * buf;
- char * pch;
- va_list vl;
-
- /* pass 1: allocate enough space for the string */
- va_start (vl, first_element);
- element = first_element;
- while (element) {
- bufLen += strlen (element) + 1;
- element = va_arg (vl, const char*);
+ const char * element;
+ char * buf;
+ char * pch;
+ va_list vl;
+ size_t bufLen = 0;
+
+ /* pass 1: allocate enough space for the string */
+ va_start (vl, first_element);
+ element = first_element;
+ while (element)
+ {
+ bufLen += strlen (element) + 1;
+ element = va_arg (vl, const char*);
}
- pch = buf = tr_new (char, bufLen);
- va_end (vl);
-
- /* pass 2: build the string piece by piece */
- va_start (vl, first_element);
- element = first_element;
- while (element) {
- const size_t elementLen = strlen (element);
- memcpy (pch, element, elementLen);
- pch += elementLen;
- *pch++ = TR_PATH_DELIMITER;
- element = va_arg (vl, const char*);
+ pch = buf = tr_new (char, bufLen);
+ va_end (vl);
+
+ /* pass 2: build the string piece by piece */
+ va_start (vl, first_element);
+ element = first_element;
+ while (element)
+ {
+ const size_t elementLen = strlen (element);
+ memcpy (pch, element, elementLen);
+ pch += elementLen;
+ *pch++ = TR_PATH_DELIMITER;
+ element = va_arg (vl, const char*);
}
- va_end (vl);
+ va_end (vl);
- /* terminate the string. if nonempty, eat the unwanted trailing slash */
- if (pch != buf)
- --pch;
- *pch++ = '\0';
+ /* terminate the string. if nonempty, eat the unwanted trailing slash */
+ if (pch != buf)
+ --pch;
+ *pch++ = '\0';
- /* sanity checks & return */
- assert (pch - buf == (off_t)bufLen);
- return buf;
+ /* sanity checks & return */
+ assert (pch - buf == (off_t)bufLen);
+ return buf;
}
#ifdef SYS_DARWIN
bool
tr_fileExists (const char * filename, time_t * mtime)
{
- struct stat sb;
- const bool ok = !stat (filename, &sb);
+ struct stat sb;
+ const bool ok = !stat (filename, &sb);
- if (ok && (mtime != NULL))
- *mtime = TR_STAT_MTIME (sb);
+ if (ok && (mtime != NULL))
+ *mtime = TR_STAT_MTIME (sb);
- return ok;
+ return ok;
}
/****
char*
evbuffer_free_to_str (struct evbuffer * buf)
{
- const size_t n = evbuffer_get_length (buf);
- char * ret = tr_new (char, n + 1);
- evbuffer_copyout (buf, ret, n);
- evbuffer_free (buf);
- ret[n] = '\0';
- return ret;
+ const size_t n = evbuffer_get_length (buf);
+ char * ret = tr_new (char, n + 1);
+ evbuffer_copyout (buf, ret, n);
+ evbuffer_free (buf);
+ ret[n] = '\0';
+ return ret;
}
char*
tr_strdup (const void * in)
{
- return tr_strndup (in, in ? (int)strlen ((const char *)in) : 0);
+ return tr_strndup (in, in ? (int)strlen ((const char *)in) : 0);
}
char*
tr_strndup (const void * in, int len)
{
- char * out = NULL;
+ char * out = NULL;
- if (len < 0)
+ if (len < 0)
{
- out = tr_strdup (in);
+ out = tr_strdup (in);
}
- else if (in)
+ else if (in)
{
- out = tr_malloc (len + 1);
- memcpy (out, in, len);
- out[len] = '\0';
+ out = tr_malloc (len + 1);
+ memcpy (out, in, len);
+ out[len] = '\0';
}
- return out;
+ return out;
}
const char*
const char * needle, size_t needlelen)
{
#ifdef HAVE_MEMMEM
- return memmem (haystack, haystacklen, needle, needlelen);
+ return memmem (haystack, haystacklen, needle, needlelen);
#else
- size_t i;
- if (!needlelen)
- return haystack;
- if (needlelen > haystacklen || !haystack || !needle)
- return NULL;
- for (i=0; i<=haystacklen-needlelen; ++i)
- if (!memcmp (haystack+i, needle, needlelen))
- return haystack+i;
+ size_t i;
+ if (!needlelen)
+ return haystack;
+ if (needlelen > haystacklen || !haystack || !needle)
return NULL;
+ for (i=0; i<=haystacklen-needlelen; ++i)
+ if (!memcmp (haystack+i, needle, needlelen))
+ return haystack+i;
+ return NULL;
#endif
}
char*
tr_strdup_printf (const char * fmt, ...)
{
- va_list ap;
- char * ret;
- size_t len;
- char statbuf[2048];
-
- va_start (ap, fmt);
- len = evutil_vsnprintf (statbuf, sizeof (statbuf), fmt, ap);
- va_end (ap);
- if (len < sizeof (statbuf))
- ret = tr_strndup (statbuf, len);
- else {
- ret = tr_new (char, len + 1);
- va_start (ap, fmt);
- evutil_vsnprintf (ret, len + 1, fmt, ap);
- va_end (ap);
+ va_list ap;
+ char * ret;
+ size_t len;
+ char statbuf[2048];
+
+ va_start (ap, fmt);
+ len = evutil_vsnprintf (statbuf, sizeof (statbuf), fmt, ap);
+ va_end (ap);
+
+ if (len < sizeof (statbuf))
+ {
+ ret = tr_strndup (statbuf, len);
+ }
+ else
+ {
+ ret = tr_new (char, len + 1);
+ va_start (ap, fmt);
+ evutil_vsnprintf (ret, len + 1, fmt, ap);
+ va_end (ap);
}
- return ret;
+ return ret;
}
const char*
tr_strerror (int i)
{
- const char * ret = strerror (i);
+ const char * ret = strerror (i);
- if (ret == NULL)
- ret = "Unknown Error";
- return ret;
+ if (ret == NULL)
+ ret = "Unknown Error";
+
+ return ret;
}
int
tr_strcmp0 (const char * str1, const char * str2)
{
- if (str1 && str2) return strcmp (str1, str2);
- if (str1) return 1;
- if (str2) return -1;
- return 0;
+ if (str1 && str2) return strcmp (str1, str2);
+ if (str1) return 1;
+ if (str2) return -1;
+ return 0;
}
/****
tr_strsep (char ** str, const char * delims)
{
#ifdef HAVE_STRSEP
- return strsep (str, delims);
+ return strsep (str, delims);
#else
- char *token;
+ char *token;
- if (*str == NULL) {
- /* No more tokens */
- return NULL;
- }
+ if (*str == NULL) /* no more tokens */
+ return NULL;
- token = *str;
- while (**str != '\0') {
- if (strchr (delims, **str) != NULL) {
- **str = '\0';
+ token = *str;
+ while (**str != '\0')
+ {
+ if (strchr (delims, **str) != NULL)
+ {
+ **str = '\0';
(*str)++;
return token;
}
(*str)++;
}
- /* There is not another token */
- *str = NULL;
+ /* there is not another token */
+ *str = NULL;
- return token;
+ return token;
#endif
}
char*
tr_strstrip (char * str)
{
- if (str != NULL)
+ if (str != NULL)
{
- size_t pos;
- size_t len = strlen (str);
+ size_t pos;
+ size_t len = strlen (str);
- while (len && isspace (str[len - 1]))
- --len;
+ while (len && isspace (str[len - 1]))
+ --len;
- for (pos = 0; pos < len && isspace (str[pos]);)
- ++pos;
+ for (pos = 0; pos < len && isspace (str[pos]);)
+ ++pos;
- len -= pos;
- memmove (str, str + pos, len);
- str[len] = '\0';
+ len -= pos;
+ memmove (str, str + pos, len);
+ str[len] = '\0';
}
- return str;
+ return str;
}
bool
tr_str_has_suffix (const char *str, const char *suffix)
{
- size_t str_len;
- size_t suffix_len;
+ size_t str_len;
+ size_t suffix_len;
- if (!str)
- return false;
- if (!suffix)
- return true;
+ if (!str)
+ return false;
+ if (!suffix)
+ return true;
- str_len = strlen (str);
- suffix_len = strlen (suffix);
- if (str_len < suffix_len)
- return false;
+ str_len = strlen (str);
+ suffix_len = strlen (suffix);
+ if (str_len < suffix_len)
+ return false;
- return !evutil_ascii_strncasecmp (str + str_len - suffix_len, suffix, suffix_len);
+ return !evutil_ascii_strncasecmp (str + str_len - suffix_len, suffix, suffix_len);
}
/****
uint64_t
tr_time_msec (void)
{
- struct timeval tv;
+ struct timeval tv;
- gettimeofday (&tv, NULL);
- return (uint64_t) tv.tv_sec * 1000 + (tv.tv_usec / 1000);
+ gettimeofday (&tv, NULL);
+ return (uint64_t) tv.tv_sec * 1000 + (tv.tv_usec / 1000);
}
void
tr_wait_msec (long int msec)
{
#ifdef WIN32
- Sleep ((DWORD)msec);
+ Sleep ((DWORD)msec);
#else
- struct timespec ts;
- ts.tv_sec = msec / 1000;
- ts.tv_nsec = (msec % 1000) * 1000000;
- nanosleep (&ts, NULL);
+ struct timespec ts;
+ ts.tv_sec = msec / 1000;
+ ts.tv_nsec = (msec % 1000) * 1000000;
+ nanosleep (&ts, NULL);
#endif
}
int
tr_snprintf (char * buf, size_t buflen, const char * fmt, ...)
{
- int len;
- va_list args;
+ int len;
+ va_list args;
- va_start (args, fmt);
- len = evutil_vsnprintf (buf, buflen, fmt, args);
- va_end (args);
- return len;
+ va_start (args, fmt);
+ len = evutil_vsnprintf (buf, buflen, fmt, args);
+ va_end (args);
+ return len;
}
/*
tr_strlcpy (char * dst, const void * src, size_t siz)
{
#ifdef HAVE_STRLCPY
- return strlcpy (dst, src, siz);
+ return strlcpy (dst, src, siz);
#else
- char * d = dst;
- const char *s = src;
- size_t n = siz;
+ char * d = dst;
+ const char *s = src;
+ size_t n = siz;
- assert (s);
- assert (d);
+ assert (s);
+ assert (d);
- /* Copy as many bytes as will fit */
- if (n != 0)
+ /* Copy as many bytes as will fit */
+ if (n != 0)
{
- while (--n != 0)
+ while (--n != 0)
{
- if ((*d++ = *s++) == '\0')
- break;
+ if ((*d++ = *s++) == '\0')
+ break;
}
}
- /* Not enough room in dst, add NUL and traverse rest of src */
- if (n == 0)
+ /* Not enough room in dst, add NUL and traverse rest of src */
+ if (n == 0)
{
- if (siz != 0)
- *d = '\0'; /* NUL-terminate dst */
- while (*s++)
- ;
+ if (siz != 0)
+ *d = '\0'; /* NUL-terminate dst */
+ while (*s++)
+ ;
}
- return s - (char*)src - 1; /* count does not include NUL */
+ return s - (char*)src - 1; /* count does not include NUL */
#endif
}
double
tr_getRatio (uint64_t numerator, uint64_t denominator)
{
- double ratio;
+ double ratio;
- if (denominator > 0)
- ratio = numerator / (double)denominator;
- else if (numerator > 0)
- ratio = TR_RATIO_INF;
- else
- ratio = TR_RATIO_NA;
+ if (denominator > 0)
+ ratio = numerator / (double)denominator;
+ else if (numerator > 0)
+ ratio = TR_RATIO_INF;
+ else
+ ratio = TR_RATIO_NA;
- return ratio;
+ return ratio;
}
void
tr_sha1_to_hex (char * out, const uint8_t * sha1)
{
- int i;
- static const char hex[] = "0123456789abcdef";
+ int i;
+ static const char hex[] = "0123456789abcdef";
- for (i=0; i<20; ++i)
+ for (i=0; i<20; ++i)
{
- const unsigned int val = *sha1++;
- *out++ = hex[val >> 4];
- *out++ = hex[val & 0xf];
+ const unsigned int val = *sha1++;
+ *out++ = hex[val >> 4];
+ *out++ = hex[val & 0xf];
}
- *out = '\0';
+ *out = '\0';
}
void
tr_hex_to_sha1 (uint8_t * out, const char * in)
{
- int i;
- static const char hex[] = "0123456789abcdef";
+ int i;
+ static const char hex[] = "0123456789abcdef";
- for (i=0; i<20; ++i)
+ for (i=0; i<20; ++i)
{
- const int hi = strchr (hex, tolower (*in++)) - hex;
- const int lo = strchr (hex, tolower (*in++)) - hex;
- *out++ = (uint8_t)((hi<<4) | lo);
+ const int hi = strchr (hex, tolower (*in++)) - hex;
+ const int lo = strchr (hex, tolower (*in++)) - hex;
+ *out++ = (uint8_t)((hi<<4) | lo);
}
}
static bool
isValidURLChars (const char * url, int url_len)
{
- const char * c;
- const char * end;
- static const char * rfc2396_valid_chars =
- "abcdefghijklmnopqrstuvwxyz" /* lowalpha */
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* upalpha */
- "0123456789" /* digit */
- "-_.!~*'()" /* mark */
- ";/?:@&=+$," /* reserved */
- "<>#%<\"" /* delims */
- "{}|\\^[]`"; /* unwise */
+ const char * c;
+ const char * end;
+ static const char * rfc2396_valid_chars =
+ "abcdefghijklmnopqrstuvwxyz" /* lowalpha */
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* upalpha */
+ "0123456789" /* digit */
+ "-_.!~*'()" /* mark */
+ ";/?:@&=+$," /* reserved */
+ "<>#%<\"" /* delims */
+ "{}|\\^[]`"; /* unwise */
- if (url == NULL)
- return false;
+ if (url == NULL)
+ return false;
- for (c=url, end=c+url_len; c && *c && c!=end; ++c)
- if (!strchr (rfc2396_valid_chars, *c))
- return false;
+ for (c=url, end=c+url_len; c && *c && c!=end; ++c)
+ if (!strchr (rfc2396_valid_chars, *c))
+ return false;
- return true;
+ return true;
}
/** @brief return true if the URL is a http or https or UDP one that Transmission understands */
bool
tr_urlIsValidTracker (const char * url)
{
- bool valid;
+ bool valid;
- if (url == NULL)
+ if (url == NULL)
{
- valid = false;
+ valid = false;
}
- else
+ else
{
- const int len = strlen (url);
+ const int len = strlen (url);
- valid = isValidURLChars (url, len)
- && !tr_urlParse (url, len, NULL, NULL, NULL, NULL)
- && (!memcmp (url,"http://",7) || !memcmp (url,"https://",8) || !memcmp (url,"udp://",6));
+ valid = isValidURLChars (url, len)
+ && !tr_urlParse (url, len, NULL, NULL, NULL, NULL)
+ && (!memcmp (url,"http://",7) || !memcmp (url,"https://",8) || !memcmp (url,"udp://",6));
}
- return valid;
+ return valid;
}
/** @brief return true if the URL is a http or https or ftp or sftp one that Transmission understands */
bool
tr_urlIsValid (const char * url, int url_len)
{
- bool valid;
+ bool valid;
- if (url == NULL)
+ if (url == NULL)
{
- valid = false;
+ valid = false;
}
- else
+ else
{
- if (url_len < 0)
- url_len = strlen (url);
+ if (url_len < 0)
+ url_len = strlen (url);
- valid = isValidURLChars (url, url_len)
- && !tr_urlParse (url, url_len, NULL, NULL, NULL, NULL)
- && (!memcmp (url,"http://",7) || !memcmp (url,"https://",8) || !memcmp (url,"ftp://",6) || !memcmp (url,"sftp://",7));
+ valid = isValidURLChars (url, url_len)
+ && !tr_urlParse (url, url_len, NULL, NULL, NULL, NULL)
+ && (!memcmp (url,"http://",7) || !memcmp (url,"https://",8) || !memcmp (url,"ftp://",6) || !memcmp (url,"sftp://",7));
}
- return valid;
+ return valid;
}
bool
tr_addressIsIP (const char * str)
{
- tr_address tmp;
- return tr_address_from_string (&tmp, str);
+ tr_address tmp;
+ return tr_address_from_string (&tmp, str);
}
int
int * setme_port,
char ** setme_path)
{
- int err;
- int port = 0;
- int n;
- char * tmp;
- char * pch;
- size_t host_len;
- size_t protocol_len;
- const char * host = NULL;
- const char * protocol = NULL;
- const char * path = NULL;
-
- tmp = tr_strndup (url_in, len);
- if ((pch = strstr (tmp, "://")))
+ int err;
+ int port = 0;
+ int n;
+ char * tmp;
+ char * pch;
+ size_t host_len;
+ size_t protocol_len;
+ const char * host = NULL;
+ const char * protocol = NULL;
+ const char * path = NULL;
+
+ tmp = tr_strndup (url_in, len);
+ if ((pch = strstr (tmp, "://")))
{
- *pch = '\0';
- protocol = tmp;
- protocol_len = pch - protocol;
- pch += 3;
-/*fprintf (stderr, "protocol is [%s]... what's left is [%s]\n", protocol, pch);*/
- if ((n = strcspn (pch, ":/")))
+ *pch = '\0';
+ protocol = tmp;
+ protocol_len = pch - protocol;
+ pch += 3;
+ if ((n = strcspn (pch, ":/")))
{
- const int havePort = pch[n] == ':';
- host = pch;
- host_len = n;
- pch += n;
- if (pch && *pch)
- *pch++ = '\0';
-/*fprintf (stderr, "host is [%s]... what's left is [%s]\n", host, pch);*/
- if (havePort)
+ const int havePort = pch[n] == ':';
+ host = pch;
+ host_len = n;
+ pch += n;
+ if (pch && *pch)
+ *pch++ = '\0';
+ if (havePort)
{
- char * end;
- port = strtol (pch, &end, 10);
- pch = end;
-/*fprintf (stderr, "port is [%d]... what's left is [%s]\n", port, pch);*/
+ char * end;
+ port = strtol (pch, &end, 10);
+ pch = end;
}
- path = pch;
-/*fprintf (stderr, "path is [%s]\n", path);*/
+ path = pch;
}
}
- err = !host || !path || !protocol;
+ err = !host || !path || !protocol;
- if (!err && !port)
+ if (!err && !port)
{
- if (!strcmp (protocol, "udp")) port = 80;
- else if (!strcmp (protocol, "ftp")) port = 21;
- else if (!strcmp (protocol, "sftp")) port = 22;
- else if (!strcmp (protocol, "http")) port = 80;
- else if (!strcmp (protocol, "https")) port = 443;
+ if (!strcmp (protocol, "udp")) port = 80;
+ else if (!strcmp (protocol, "ftp")) port = 21;
+ else if (!strcmp (protocol, "sftp")) port = 22;
+ else if (!strcmp (protocol, "http")) port = 80;
+ else if (!strcmp (protocol, "https")) port = 443;
}
- if (!err)
+ if (!err)
{
- if (setme_protocol) *setme_protocol = tr_strndup (protocol, protocol_len);
-
- if (setme_host){ ((char*)host)[-3] = ':'; *setme_host =
- tr_strndup (host, host_len); }
- if (setme_path){ if (!*path) *setme_path = tr_strdup ("/");
- else if (path[0] == '/') *setme_path = tr_strdup (path);
- else { ((char*)path)[-1] = '/'; *setme_path = tr_strdup (path - 1); } }
- if (setme_port) *setme_port = port;
+ if (setme_protocol) *setme_protocol = tr_strndup (protocol, protocol_len);
+
+ if (setme_host){ ((char*)host)[-3] = ':'; *setme_host =
+ tr_strndup (host, host_len); }
+
+ if (setme_path){ if (!*path) *setme_path = tr_strdup ("/");
+ else if (path[0] == '/') *setme_path = tr_strdup (path);
+ else { ((char*)path)[-1] = '/'; *setme_path = tr_strdup (path - 1); } }
+
+ if (setme_port) *setme_port = port;
}
- tr_free (tmp);
- return err;
+ tr_free (tmp);
+ return err;
}
#include <string.h>
char *
tr_base64_encode (const void * input, int length, int * setme_len)
{
- int retlen = 0;
- char * ret = NULL;
+ int retlen = 0;
+ char * ret = NULL;
- if (input != NULL)
+ if (input != NULL)
{
- BIO * b64;
- BIO * bmem;
- BUF_MEM * bptr;
-
- if (length < 1)
- length = (int)strlen (input);
-
- bmem = BIO_new (BIO_s_mem ());
- b64 = BIO_new (BIO_f_base64 ());
- BIO_set_flags (b64, BIO_FLAGS_BASE64_NO_NL);
- b64 = BIO_push (b64, bmem);
- BIO_write (b64, input, length);
+ BIO * b64;
+ BIO * bmem;
+ BUF_MEM * bptr;
+
+ if (length < 1)
+ length = (int)strlen (input);
+
+ bmem = BIO_new (BIO_s_mem ());
+ b64 = BIO_new (BIO_f_base64 ());
+ BIO_set_flags (b64, BIO_FLAGS_BASE64_NO_NL);
+ b64 = BIO_push (b64, bmem);
+ BIO_write (b64, input, length);
(void) BIO_flush (b64);
- BIO_get_mem_ptr (b64, &bptr);
- ret = tr_strndup (bptr->data, bptr->length);
- retlen = bptr->length;
- BIO_free_all (b64);
+ BIO_get_mem_ptr (b64, &bptr);
+ ret = tr_strndup (bptr->data, bptr->length);
+ retlen = bptr->length;
+ BIO_free_all (b64);
}
- if (setme_len)
- *setme_len = retlen;
+ if (setme_len)
+ *setme_len = retlen;
- return ret;
+ return ret;
}
char *
int length,
int * setme_len)
{
- char * ret;
- BIO * b64;
- BIO * bmem;
- int retlen;
+ char * ret;
+ BIO * b64;
+ BIO * bmem;
+ int retlen;
- if (length < 1)
- length = strlen (input);
+ if (length < 1)
+ length = strlen (input);
- ret = tr_new0 (char, length);
- b64 = BIO_new (BIO_f_base64 ());
- bmem = BIO_new_mem_buf ((unsigned char*)input, length);
- bmem = BIO_push (b64, bmem);
- retlen = BIO_read (bmem, ret, length);
- if (!retlen)
+ ret = tr_new0 (char, length);
+ b64 = BIO_new (BIO_f_base64 ());
+ bmem = BIO_new_mem_buf ((unsigned char*)input, length);
+ bmem = BIO_push (b64, bmem);
+ retlen = BIO_read (bmem, ret, length);
+ if (!retlen)
{
- /* try again, but with the BIO_FLAGS_BASE64_NO_NL flag */
- BIO_free_all (bmem);
- b64 = BIO_new (BIO_f_base64 ());
- BIO_set_flags (b64, BIO_FLAGS_BASE64_NO_NL);
- bmem = BIO_new_mem_buf ((unsigned char*)input, length);
- bmem = BIO_push (b64, bmem);
- retlen = BIO_read (bmem, ret, length);
+ /* try again, but with the BIO_FLAGS_BASE64_NO_NL flag */
+ BIO_free_all (bmem);
+ b64 = BIO_new (BIO_f_base64 ());
+ BIO_set_flags (b64, BIO_FLAGS_BASE64_NO_NL);
+ bmem = BIO_new_mem_buf ((unsigned char*)input, length);
+ bmem = BIO_push (b64, bmem);
+ retlen = BIO_read (bmem, ret, length);
}
- if (setme_len)
- *setme_len = retlen;
+ if (setme_len)
+ *setme_len = retlen;
- BIO_free_all (bmem);
- return ret;
+ BIO_free_all (bmem);
+ return ret;
}
/***
size_t sizeof_element,
size_t nmemb)
{
- char * a = array;
+ char * a = array;
- memmove (a + sizeof_element * index_to_remove,
- a + sizeof_element * (index_to_remove + 1),
- sizeof_element * (--nmemb - index_to_remove));
+ memmove (a + sizeof_element * index_to_remove,
+ a + sizeof_element * (index_to_remove + 1),
+ sizeof_element * (--nmemb - index_to_remove));
}
int
int (* compar)(const void* key, const void* arrayMember),
bool * exact_match)
{
- size_t first = 0;
- const char * cbase = base;
- bool exact = false;
+ size_t first = 0;
+ const char * cbase = base;
+ bool exact = false;
- while (nmemb != 0)
+ while (nmemb != 0)
{
- const size_t half = nmemb / 2;
- const size_t middle = first + half;
- const int c = compar (key, cbase + size*middle);
-
- if (c <= 0) {
- if (c == 0)
- exact = true;
- nmemb = half;
- } else {
- first = middle + 1;
- nmemb = nmemb - half - 1;
+ const size_t half = nmemb / 2;
+ const size_t middle = first + half;
+ const int c = compar (key, cbase + size*middle);
+
+ if (c <= 0)
+ {
+ if (c == 0)
+ exact = true;
+ nmemb = half;
+ }
+ else
+ {
+ first = middle + 1;
+ nmemb = nmemb - half - 1;
}
}
- *exact_match = exact;
-
- return first;
+ *exact_match = exact;
+ return first;
}
/***
static char*
strip_non_utf8 (const char * in, size_t inlen)
{
- const char * end;
- const char zero = '\0';
- struct evbuffer * buf = evbuffer_new ();
+ const char * end;
+ const char zero = '\0';
+ struct evbuffer * buf = evbuffer_new ();
- while (!tr_utf8_validate (in, inlen, &end))
+ while (!tr_utf8_validate (in, inlen, &end))
{
- const int good_len = end - in;
+ const int good_len = end - in;
- evbuffer_add (buf, in, good_len);
- inlen -= (good_len + 1);
- in += (good_len + 1);
- evbuffer_add (buf, "?", 1);
+ evbuffer_add (buf, in, good_len);
+ inlen -= (good_len + 1);
+ in += (good_len + 1);
+ evbuffer_add (buf, "?", 1);
}
- evbuffer_add (buf, in, inlen);
- evbuffer_add (buf, &zero, 1);
- return evbuffer_free_to_str (buf);
+ evbuffer_add (buf, in, inlen);
+ evbuffer_add (buf, &zero, 1);
+ return evbuffer_free_to_str (buf);
}
static char*
to_utf8 (const char * in, size_t inlen)
{
- char * ret = NULL;
+ char * ret = NULL;
#ifdef HAVE_ICONV_OPEN
- int i;
- const char * encodings[] = { "CURRENT", "ISO-8859-15" };
- const int encoding_count = sizeof (encodings) / sizeof (encodings[1]);
- const size_t buflen = inlen*4 + 10;
- char * out = tr_new (char, buflen);
+ int i;
+ const char * encodings[] = { "CURRENT", "ISO-8859-15" };
+ const int encoding_count = sizeof (encodings) / sizeof (encodings[1]);
+ const size_t buflen = inlen*4 + 10;
+ char * out = tr_new (char, buflen);
- for (i=0; !ret && i<encoding_count; ++i)
+ for (i=0; !ret && i<encoding_count; ++i)
{
- char * inbuf = (char*) in;
- char * outbuf = out;
- size_t inbytesleft = inlen;
- size_t outbytesleft = buflen;
- const char * test_encoding = encodings[i];
-
- iconv_t cd = iconv_open ("UTF-8", test_encoding);
- if (cd != (iconv_t)-1) {
- if (iconv (cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft) != (size_t)-1)
- ret = tr_strndup (out, buflen-outbytesleft);
- iconv_close (cd);
+ char * inbuf = (char*) in;
+ char * outbuf = out;
+ size_t inbytesleft = inlen;
+ size_t outbytesleft = buflen;
+ const char * test_encoding = encodings[i];
+
+ iconv_t cd = iconv_open ("UTF-8", test_encoding);
+ if (cd != (iconv_t)-1)
+ {
+ if (iconv (cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft) != (size_t)-1)
+ ret = tr_strndup (out, buflen-outbytesleft);
+ iconv_close (cd);
}
}
- tr_free (out);
+ tr_free (out);
#endif
- if (ret == NULL)
- ret = strip_non_utf8 (in, inlen);
+ if (ret == NULL)
+ ret = strip_non_utf8 (in, inlen);
- return ret;
+ return ret;
}
char*
tr_utf8clean (const char * str, int max_len)
{
- char * ret;
- const char * end;
+ char * ret;
+ const char * end;
- if (max_len < 0)
- max_len = (int) strlen (str);
+ if (max_len < 0)
+ max_len = (int) strlen (str);
- if (tr_utf8_validate (str, max_len, &end))
- ret = tr_strndup (str, max_len);
- else
- ret = to_utf8 (str, max_len);
+ if (tr_utf8_validate (str, max_len, &end))
+ ret = tr_strndup (str, max_len);
+ else
+ ret = to_utf8 (str, max_len);
- assert (tr_utf8_validate (ret, -1, NULL));
- return ret;
+ assert (tr_utf8_validate (ret, -1, NULL));
+ return ret;
}
/***
struct number_range
{
- int low;
- int high;
+ int low;
+ int high;
};
/**
static bool
parseNumberSection (const char * str, int len, struct number_range * setme)
{
- long a, b;
- bool success;
- char * end;
- const int error = errno;
- char * tmp = tr_strndup (str, len);
+ long a, b;
+ bool success;
+ char * end;
+ const int error = errno;
+ char * tmp = tr_strndup (str, len);
- errno = 0;
- a = b = strtol (tmp, &end, 10);
- if (errno || (end == tmp)) {
+ errno = 0;
+ a = b = strtol (tmp, &end, 10);
+ if (errno || (end == tmp))
+ {
+ success = false;
+ }
+ else if (*end != '-')
+ {
+ success = true;
+ }
+ else
+ {
+ const char * pch = end + 1;
+ b = strtol (pch, &end, 10);
+ if (errno || (pch == end))
success = false;
- } else if (*end != '-') {
+ else if (*end) /* trailing data */
+ success = false;
+ else
success = true;
- } else {
- const char * pch = end + 1;
- b = strtol (pch, &end, 10);
- if (errno || (pch == end))
- success = false;
- else if (*end) /* trailing data */
- success = false;
- else
- success = true;
}
- tr_free (tmp);
- setme->low = MIN (a, b);
- setme->high = MAX (a, b);
+ tr_free (tmp);
+
+ setme->low = MIN (a, b);
+ setme->high = MAX (a, b);
- errno = error;
- return success;
+ errno = error;
+ return success;
}
int
compareInt (const void * va, const void * vb)
{
- const int a = * (const int *)va;
- const int b = * (const int *)vb;
- return a - b;
+ const int a = * (const int *)va;
+ const int b = * (const int *)vb;
+ return a - b;
}
/**
int*
tr_parseNumberRange (const char * str_in, int len, int * setmeCount)
{
- int n = 0;
- int * uniq = NULL;
- char * str = tr_strndup (str_in, len);
- const char * walk;
- tr_list * ranges = NULL;
- bool success = true;
-
- walk = str;
- while (walk && *walk && success) {
- struct number_range range;
- const char * pch = strchr (walk, ',');
- if (pch) {
- success = parseNumberSection (walk, pch-walk, &range);
- walk = pch + 1;
- } else {
- success = parseNumberSection (walk, strlen (walk), &range);
- walk += strlen (walk);
+ int n = 0;
+ int * uniq = NULL;
+ char * str = tr_strndup (str_in, len);
+ const char * walk;
+ tr_list * ranges = NULL;
+ bool success = true;
+
+ walk = str;
+ while (walk && *walk && success)
+ {
+ struct number_range range;
+ const char * pch = strchr (walk, ',');
+ if (pch)
+ {
+ success = parseNumberSection (walk, pch-walk, &range);
+ walk = pch + 1;
}
- if (success)
- tr_list_append (&ranges, tr_memdup (&range, sizeof (struct number_range)));
+ else
+ {
+ success = parseNumberSection (walk, strlen (walk), &range);
+ walk += strlen (walk);
+ }
+ if (success)
+ tr_list_append (&ranges, tr_memdup (&range, sizeof (struct number_range)));
}
- if (!success)
+ if (!success)
{
- *setmeCount = 0;
- uniq = NULL;
+ *setmeCount = 0;
+ uniq = NULL;
}
- else
+ else
{
- int i;
- int n2;
- tr_list * l;
- int * sorted = NULL;
-
- /* build a sorted number array */
- n = n2 = 0;
- for (l=ranges; l!=NULL; l=l->next) {
- const struct number_range * r = l->data;
- n += r->high + 1 - r->low;
+ int i;
+ int n2;
+ tr_list * l;
+ int * sorted = NULL;
+
+ /* build a sorted number array */
+ n = n2 = 0;
+ for (l=ranges; l!=NULL; l=l->next)
+ {
+ const struct number_range * r = l->data;
+ n += r->high + 1 - r->low;
}
- sorted = tr_new (int, n);
- for (l=ranges; l!=NULL; l=l->next) {
- const struct number_range * r = l->data;
- int i;
- for (i=r->low; i<=r->high; ++i)
- sorted[n2++] = i;
+ sorted = tr_new (int, n);
+ for (l=ranges; l!=NULL; l=l->next)
+ {
+ int i;
+ const struct number_range * r = l->data;
+ for (i=r->low; i<=r->high; ++i)
+ sorted[n2++] = i;
}
- qsort (sorted, n, sizeof (int), compareInt);
- assert (n == n2);
+ qsort (sorted, n, sizeof (int), compareInt);
+ assert (n == n2);
- /* remove duplicates */
- uniq = tr_new (int, n);
- for (i=n=0; i<n2; ++i)
- if (!n || uniq[n-1] != sorted[i])
- uniq[n++] = sorted[i];
+ /* remove duplicates */
+ uniq = tr_new (int, n);
+ for (i=n=0; i<n2; ++i)
+ if (!n || uniq[n-1] != sorted[i])
+ uniq[n++] = sorted[i];
- tr_free (sorted);
+ tr_free (sorted);
}
- /* cleanup */
- tr_list_free (&ranges, tr_free);
- tr_free (str);
+ /* cleanup */
+ tr_list_free (&ranges, tr_free);
+ tr_free (str);
- /* return the result */
- *setmeCount = n;
- return uniq;
+ /* return the result */
+ *setmeCount = n;
+ return uniq;
}
/***
double
tr_truncd (double x, int precision)
{
- char * pt;
- char buf[128];
- const int max_precision = (int) log10 (1.0 / DBL_EPSILON) - 1;
- tr_snprintf (buf, sizeof (buf), "%.*f", max_precision, x);
- if ((pt = strstr (buf, localeconv ()->decimal_point)))
- pt[precision ? precision+1 : 0] = '\0';
- return atof (buf);
+ char * pt;
+ char buf[128];
+ const int max_precision = (int) log10 (1.0 / DBL_EPSILON) - 1;
+ tr_snprintf (buf, sizeof (buf), "%.*f", max_precision, x);
+ if ((pt = strstr (buf, localeconv ()->decimal_point)))
+ pt[precision ? precision+1 : 0] = '\0';
+ return atof (buf);
}
/* return a truncated double as a string */
static char*
tr_strtruncd (char * buf, double x, int precision, size_t buflen)
{
- tr_snprintf (buf, buflen, "%.*f", precision, tr_truncd (x, precision));
- return buf;
+ tr_snprintf (buf, buflen, "%.*f", precision, tr_truncd (x, precision));
+ return buf;
}
char*
tr_strpercent (char * buf, double x, size_t buflen)
{
- if (x < 10.0)
- tr_strtruncd (buf, x, 2, buflen);
- else if (x < 100.0)
- tr_strtruncd (buf, x, 1, buflen);
- else
- tr_strtruncd (buf, x, 0, buflen);
- return buf;
+ if (x < 10.0)
+ tr_strtruncd (buf, x, 2, buflen);
+ else if (x < 100.0)
+ tr_strtruncd (buf, x, 1, buflen);
+ else
+ tr_strtruncd (buf, x, 0, buflen);
+
+ return buf;
}
char*
tr_strratio (char * buf, size_t buflen, double ratio, const char * infinity)
{
- if ((int)ratio == TR_RATIO_NA)
- tr_strlcpy (buf, _("None"), buflen);
- else if ((int)ratio == TR_RATIO_INF)
- tr_strlcpy (buf, infinity, buflen);
- else
- tr_strpercent (buf, ratio, buflen);
- return buf;
+ if ((int)ratio == TR_RATIO_NA)
+ tr_strlcpy (buf, _("None"), buflen);
+ else if ((int)ratio == TR_RATIO_INF)
+ tr_strlcpy (buf, infinity, buflen);
+ else
+ tr_strpercent (buf, ratio, buflen);
+
+ return buf;
}
/***
int
tr_moveFile (const char * oldpath, const char * newpath, bool * renamed)
{
- int in;
- int out;
- char * buf;
- struct stat st;
- off_t bytesLeft;
- const size_t buflen = 1024 * 128; /* 128 KiB buffer */
-
- /* make sure the old file exists */
- if (stat (oldpath, &st)) {
- const int err = errno;
- errno = err;
- return -1;
- }
- if (!S_ISREG (st.st_mode)) {
- errno = ENOENT;
- return -1;
- }
- bytesLeft = st.st_size;
+ int in;
+ int out;
+ char * buf;
+ struct stat st;
+ off_t bytesLeft;
+ const size_t buflen = 1024 * 128; /* 128 KiB buffer */
- /* make sure the target directory exists */
+ /* make sure the old file exists */
+ if (stat (oldpath, &st))
{
- char * newdir = tr_dirname (newpath);
- int i = tr_mkdirp (newdir, 0777);
- tr_free (newdir);
- if (i)
- return i;
+ const int err = errno;
+ errno = err;
+ return -1;
}
-
- /* they might be on the same filesystem... */
+ if (!S_ISREG (st.st_mode))
{
- const int i = rename (oldpath, newpath);
- if (renamed != NULL)
- *renamed = i == 0;
- if (!i)
- return 0;
+ errno = ENOENT;
+ return -1;
}
-
- /* copy the file */
- in = tr_open_file_for_scanning (oldpath);
- out = tr_open_file_for_writing (newpath);
- buf = tr_valloc (buflen);
- while (bytesLeft > 0)
+ bytesLeft = st.st_size;
+
+ /* make sure the target directory exists */
+ {
+ char * newdir = tr_dirname (newpath);
+ int i = tr_mkdirp (newdir, 0777);
+ tr_free (newdir);
+ if (i)
+ return i;
+ }
+
+ /* they might be on the same filesystem... */
+ {
+ const int i = rename (oldpath, newpath);
+ if (renamed != NULL)
+ *renamed = i == 0;
+ if (!i)
+ return 0;
+ }
+
+ /* copy the file */
+ in = tr_open_file_for_scanning (oldpath);
+ out = tr_open_file_for_writing (newpath);
+ buf = tr_valloc (buflen);
+ while (bytesLeft > 0)
{
- ssize_t bytesWritten;
- const off_t bytesThisPass = MIN (bytesLeft, (off_t)buflen);
- const int numRead = read (in, buf, bytesThisPass);
- if (numRead < 0)
- break;
- bytesWritten = write (out, buf, numRead);
- if (bytesWritten < 0)
- break;
- bytesLeft -= bytesWritten;
+ ssize_t bytesWritten;
+ const off_t bytesThisPass = MIN (bytesLeft, (off_t)buflen);
+ const int numRead = read (in, buf, bytesThisPass);
+ if (numRead < 0)
+ break;
+ bytesWritten = write (out, buf, numRead);
+ if (bytesWritten < 0)
+ break;
+ bytesLeft -= bytesWritten;
}
- /* cleanup */
- tr_free (buf);
- tr_close_file (out);
- tr_close_file (in);
- if (bytesLeft != 0)
- return -1;
+ /* cleanup */
+ tr_free (buf);
+ tr_close_file (out);
+ tr_close_file (in);
+ if (bytesLeft != 0)
+ return -1;
- unlink (oldpath);
- return 0;
+ unlink (oldpath);
+ return 0;
}
bool
tr_is_same_file (const char * filename1, const char * filename2)
{
- struct stat sb1, sb2;
+ struct stat sb1, sb2;
- return !stat (filename1, &sb1)
- && !stat (filename2, &sb2)
- && (sb1.st_dev == sb2.st_dev)
- && (sb1.st_ino == sb2.st_ino);
+ return !stat (filename1, &sb1)
+ && !stat (filename2, &sb2)
+ && (sb1.st_dev == sb2.st_dev)
+ && (sb1.st_ino == sb2.st_ino);
}
/***
void*
tr_valloc (size_t bufLen)
{
- size_t allocLen;
- void * buf = NULL;
- static size_t pageSize = 0;
+ size_t allocLen;
+ void * buf = NULL;
+ static size_t pageSize = 0;
- if (!pageSize) {
+ if (!pageSize)
+ {
#ifdef HAVE_GETPAGESIZE
- pageSize = (size_t) getpagesize ();
+ pageSize = (size_t) getpagesize ();
#else /* guess */
- pageSize = 4096;
+ pageSize = 4096;
#endif
}
- allocLen = pageSize;
- while (allocLen < bufLen)
- allocLen += pageSize;
+ allocLen = pageSize;
+ while (allocLen < bufLen)
+ allocLen += pageSize;
#ifdef HAVE_POSIX_MEMALIGN
- if (!buf)
- if (posix_memalign (&buf, pageSize, allocLen))
- buf = NULL; /* just retry with valloc/malloc */
+ if (!buf)
+ if (posix_memalign (&buf, pageSize, allocLen))
+ buf = NULL; /* just retry with valloc/malloc */
#endif
#ifdef HAVE_VALLOC
- if (!buf)
- buf = valloc (allocLen);
+ if (!buf)
+ buf = valloc (allocLen);
#endif
- if (!buf)
- buf = tr_malloc (allocLen);
+ if (!buf)
+ buf = tr_malloc (allocLen);
- return buf;
+ return buf;
}
char *
tr_realpath (const char * path, char * resolved_path)
{
#ifdef WIN32
- /* From a message to the Mingw-msys list, Jun 2, 2005 by Mark Junker. */
- if (GetFullPathNameA (path, TR_PATH_MAX, resolved_path, NULL) == 0)
- return NULL;
- return resolved_path;
+ /* From a message to the Mingw-msys list, Jun 2, 2005 by Mark Junker. */
+ if (GetFullPathNameA (path, TR_PATH_MAX, resolved_path, NULL) == 0)
+ return NULL;
+ return resolved_path;
#else
- return realpath (path, resolved_path);
+ return realpath (path, resolved_path);
#endif
}
tr_htonll (uint64_t x)
{
#ifdef HAVE_HTONLL
- return htonll (x);
+ return htonll (x);
#else
- /* fallback code by bdonlan at
- * http://stackoverflow.com/questions/809902/64-bit-ntohl-in-c/875505#875505 */
- union { uint32_t lx[2]; uint64_t llx; } u;
- u.lx[0] = htonl (x >> 32);
- u.lx[1] = htonl (x & 0xFFFFFFFFULL);
- return u.llx;
+ /* fallback code by bdonlan at
+ * http://stackoverflow.com/questions/809902/64-bit-ntohl-in-c/875505#875505 */
+ union { uint32_t lx[2]; uint64_t llx; } u;
+ u.lx[0] = htonl (x >> 32);
+ u.lx[1] = htonl (x & 0xFFFFFFFFULL);
+ return u.llx;
#endif
}
tr_ntohll (uint64_t x)
{
#ifdef HAVE_NTOHLL
- return ntohll (x);
+ return ntohll (x);
#else
- /* fallback code by bdonlan at
- * http://stackoverflow.com/questions/809902/64-bit-ntohl-in-c/875505#875505 */
- union { uint32_t lx[2]; uint64_t llx; } u;
- u.llx = x;
- return ((uint64_t)ntohl (u.lx[0]) << 32) | (uint64_t)ntohl (u.lx[1]);
+ /* fallback code by bdonlan at
+ * http://stackoverflow.com/questions/809902/64-bit-ntohl-in-c/875505#875505 */
+ union { uint32_t lx[2]; uint64_t llx; } u;
+ u.llx = x;
+ return ((uint64_t)ntohl (u.lx[0]) << 32) | (uint64_t)ntohl (u.lx[1]);
#endif
}
struct formatter_unit
{
- char * name;
- int64_t value;
+ char * name;
+ int64_t value;
};
struct formatter_units
{
- struct formatter_unit units[4];
+ struct formatter_unit units[4];
};
enum { TR_FMT_KB, TR_FMT_MB, TR_FMT_GB, TR_FMT_TB };
const char * kb, const char * mb,
const char * gb, const char * tb)
{
- uint64_t value = kilo;
- units->units[TR_FMT_KB].name = tr_strdup (kb);
- units->units[TR_FMT_KB].value = value;
+ uint64_t value;
+
+ value = kilo;
+ units->units[TR_FMT_KB].name = tr_strdup (kb);
+ units->units[TR_FMT_KB].value = value;
- value *= kilo;
- units->units[TR_FMT_MB].name = tr_strdup (mb);
- units->units[TR_FMT_MB].value = value;
+ value *= kilo;
+ units->units[TR_FMT_MB].name = tr_strdup (mb);
+ units->units[TR_FMT_MB].value = value;
- value *= kilo;
- units->units[TR_FMT_GB].name = tr_strdup (gb);
- units->units[TR_FMT_GB].value = value;
+ value *= kilo;
+ units->units[TR_FMT_GB].name = tr_strdup (gb);
+ units->units[TR_FMT_GB].value = value;
- value *= kilo;
- units->units[TR_FMT_TB].name = tr_strdup (tb);
- units->units[TR_FMT_TB].value = value;
+ value *= kilo;
+ units->units[TR_FMT_TB].name = tr_strdup (tb);
+ units->units[TR_FMT_TB].value = value;
}
static char*
formatter_get_size_str (const struct formatter_units * u,
char * buf, int64_t bytes, size_t buflen)
{
- int precision;
- double value;
- const char * units;
- const struct formatter_unit * unit;
+ int precision;
+ double value;
+ const char * units;
+ const struct formatter_unit * unit;
+
+ if (bytes < u->units[1].value) unit = &u->units[0];
+ else if (bytes < u->units[2].value) unit = &u->units[1];
+ else if (bytes < u->units[3].value) unit = &u->units[2];
+ else unit = &u->units[3];
- if (bytes < u->units[1].value) unit = &u->units[0];
- else if (bytes < u->units[2].value) unit = &u->units[1];
- else if (bytes < u->units[3].value) unit = &u->units[2];
- else unit = &u->units[3];
+ value = (double)bytes / unit->value;
+ units = unit->name;
- value = (double)bytes / unit->value;
- units = unit->name;
- if (unit->value == 1)
- precision = 0;
- else if (value < 100)
- precision = 2;
- else
- precision = 1;
- tr_snprintf (buf, buflen, "%.*f %s", precision, value, units);
- return buf;
+ if (unit->value == 1)
+ precision = 0;
+ else if (value < 100)
+ precision = 2;
+ else
+ precision = 1;
+
+ tr_snprintf (buf, buflen, "%.*f %s", precision, value, units);
+ return buf;
}
static struct formatter_units size_units;
const char * kb, const char * mb,
const char * gb, const char * tb)
{
- formatter_init (&size_units, kilo, kb, mb, gb, tb);
+ formatter_init (&size_units, kilo, kb, mb, gb, tb);
}
char*
tr_formatter_size_B (char * buf, int64_t bytes, size_t buflen)
{
- return formatter_get_size_str (&size_units, buf, bytes, buflen);
+ return formatter_get_size_str (&size_units, buf, bytes, buflen);
}
static struct formatter_units speed_units;
const char * kb, const char * mb,
const char * gb, const char * tb)
{
- tr_speed_K = kilo;
- formatter_init (&speed_units, kilo, kb, mb, gb, tb);
+ tr_speed_K = kilo;
+ formatter_init (&speed_units, kilo, kb, mb, gb, tb);
}
char*
tr_formatter_speed_KBps (char * buf, double KBps, size_t buflen)
{
- const double K = speed_units.units[TR_FMT_KB].value;
- double speed = KBps;
-
- if (speed <= 999.95) /* 0.0 KB to 999.9 KB */
- tr_snprintf (buf, buflen, "%d %s", (int)speed, speed_units.units[TR_FMT_KB].name);
- else {
- speed /= K;
- if (speed <= 99.995) /* 0.98 MB to 99.99 MB */
- tr_snprintf (buf, buflen, "%.2f %s", speed, speed_units.units[TR_FMT_MB].name);
- else if (speed <= 999.95) /* 100.0 MB to 999.9 MB */
- tr_snprintf (buf, buflen, "%.1f %s", speed, speed_units.units[TR_FMT_MB].name);
- else {
- speed /= K;
- tr_snprintf (buf, buflen, "%.1f %s", speed, speed_units.units[TR_FMT_GB].name);
- }
+ const double K = speed_units.units[TR_FMT_KB].value;
+ double speed = KBps;
+
+ if (speed <= 999.95) /* 0.0 KB to 999.9 KB */
+ {
+ tr_snprintf (buf, buflen, "%d %s", (int)speed, speed_units.units[TR_FMT_KB].name);
+ }
+ else
+ {
+ speed /= K;
+
+ if (speed <= 99.995) /* 0.98 MB to 99.99 MB */
+ tr_snprintf (buf, buflen, "%.2f %s", speed, speed_units.units[TR_FMT_MB].name);
+ else if (speed <= 999.95) /* 100.0 MB to 999.9 MB */
+ tr_snprintf (buf, buflen, "%.1f %s", speed, speed_units.units[TR_FMT_MB].name);
+ else
+ tr_snprintf (buf, buflen, "%.1f %s", speed/K, speed_units.units[TR_FMT_GB].name);
}
- return buf;
+ return buf;
}
static struct formatter_units mem_units;
const char * kb, const char * mb,
const char * gb, const char * tb)
{
- tr_mem_K = kilo;
- formatter_init (&mem_units, kilo, kb, mb, gb, tb);
+ tr_mem_K = kilo;
+ formatter_init (&mem_units, kilo, kb, mb, gb, tb);
}
char*
tr_formatter_mem_B (char * buf, int64_t bytes_per_second, size_t buflen)
{
- return formatter_get_size_str (&mem_units, buf, bytes_per_second, buflen);
+ return formatter_get_size_str (&mem_units, buf, bytes_per_second, buflen);
}
void
enum
{
- THREADFUNC_MAX_SLEEP_MSEC = 1000,
+ THREADFUNC_MAX_SLEEP_MSEC = 1000,
};
#if 0
#define dbgmsg(...) \
- do { \
- fprintf (stderr, __VA_ARGS__); \
- fprintf (stderr, "\n"); \
- } while (0)
+ do { \
+ fprintf (stderr, __VA_ARGS__); \
+ fprintf (stderr, "\n"); \
+ } while (0)
#else
#define dbgmsg(...) \
- do { \
- if (tr_deepLoggingIsActive ()) \
- tr_deepLog (__FILE__, __LINE__, "web", __VA_ARGS__); \
- } while (0)
+ do { \
+ if (tr_deepLoggingIsActive ()) \
+ tr_deepLog (__FILE__, __LINE__, "web", __VA_ARGS__); \
+ } while (0)
#endif
/***
struct tr_web_task
{
- long code;
- long timeout_secs;
- bool did_connect;
- bool did_timeout;
- struct evbuffer * response;
- struct evbuffer * freebuf;
- char * url;
- char * range;
- char * cookies;
- tr_session * session;
- tr_web_done_func * done_func;
- void * done_func_user_data;
- CURL * curl_easy;
- struct tr_web_task * next;
+ long code;
+ long timeout_secs;
+ bool did_connect;
+ bool did_timeout;
+ struct evbuffer * response;
+ struct evbuffer * freebuf;
+ char * url;
+ char * range;
+ char * cookies;
+ tr_session * session;
+ tr_web_done_func * done_func;
+ void * done_func_user_data;
+ CURL * curl_easy;
+ struct tr_web_task * next;
};
static void
task_free (struct tr_web_task * task)
{
- if (task->freebuf)
- evbuffer_free (task->freebuf);
- tr_free (task->cookies);
- tr_free (task->range);
- tr_free (task->url);
- tr_free (task);
+ if (task->freebuf)
+ evbuffer_free (task->freebuf);
+ tr_free (task->cookies);
+ tr_free (task->range);
+ tr_free (task->url);
+ tr_free (task);
}
/***
struct tr_web
{
- bool curl_verbose;
- bool curl_ssl_verify;
- const char * curl_ca_bundle;
- int close_mode;
- struct tr_web_task * tasks;
- tr_lock * taskLock;
- char * cookie_filename;
+ bool curl_verbose;
+ bool curl_ssl_verify;
+ const char * curl_ca_bundle;
+ int close_mode;
+ struct tr_web_task * tasks;
+ tr_lock * taskLock;
+ char * cookie_filename;
};
/***
static size_t
writeFunc (void * ptr, size_t size, size_t nmemb, void * vtask)
{
- const size_t byteCount = size * nmemb;
- struct tr_web_task * task = vtask;
- evbuffer_add (task->response, ptr, byteCount);
- dbgmsg ("wrote %zu bytes to task %p's buffer", byteCount, task);
- return byteCount;
+ const size_t byteCount = size * nmemb;
+ struct tr_web_task * task = vtask;
+ evbuffer_add (task->response, ptr, byteCount);
+ dbgmsg ("wrote %zu bytes to task %p's buffer", byteCount, task);
+ return byteCount;
}
#ifdef USE_LIBCURL_SOCKOPT
static int
sockoptfunction (void * vtask, curl_socket_t fd, curlsocktype purpose UNUSED)
{
- struct tr_web_task * task = vtask;
- const bool isScrape = strstr (task->url, "scrape") != NULL;
- const bool isAnnounce = strstr (task->url, "announce") != NULL;
+ struct tr_web_task * task = vtask;
+ const bool isScrape = strstr (task->url, "scrape") != NULL;
+ const bool isAnnounce = strstr (task->url, "announce") != NULL;
- /* announce and scrape requests have tiny payloads. */
- if (isScrape || isAnnounce)
+ /* announce and scrape requests have tiny payloads. */
+ if (isScrape || isAnnounce)
{
- const int sndbuf = 1024;
- const int rcvbuf = isScrape ? 2048 : 3072;
- setsockopt (fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof (sndbuf));
- setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof (rcvbuf));
+ const int sndbuf = 1024;
+ const int rcvbuf = isScrape ? 2048 : 3072;
+ setsockopt (fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof (sndbuf));
+ setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof (rcvbuf));
}
- /* return nonzero if this function encountered an error */
- return 0;
+ /* return nonzero if this function encountered an error */
+ return 0;
}
#endif
static long
getTimeoutFromURL (const struct tr_web_task * task)
{
- long timeout;
- const tr_session * session = task->session;
+ long timeout;
+ const tr_session * session = task->session;
- if (!session || session->isClosed) timeout = 20L;
- else if (strstr (task->url, "scrape") != NULL) timeout = 30L;
- else if (strstr (task->url, "announce") != NULL) timeout = 90L;
- else timeout = 240L;
+ if (!session || session->isClosed) timeout = 20L;
+ else if (strstr (task->url, "scrape") != NULL) timeout = 30L;
+ else if (strstr (task->url, "announce") != NULL) timeout = 90L;
+ else timeout = 240L;
- return timeout;
+ return timeout;
}
static CURL *
createEasy (tr_session * s, struct tr_web * web, struct tr_web_task * task)
{
- bool is_default_value;
- const tr_address * addr;
- CURL * e = task->curl_easy = curl_easy_init ();
-
- task->timeout_secs = getTimeoutFromURL (task);
-
- curl_easy_setopt (e, CURLOPT_AUTOREFERER, 1L);
- curl_easy_setopt (e, CURLOPT_COOKIEFILE, web->cookie_filename);
- curl_easy_setopt (e, CURLOPT_ENCODING, "gzip;q=1.0, deflate, identity");
- curl_easy_setopt (e, CURLOPT_FOLLOWLOCATION, 1L);
- curl_easy_setopt (e, CURLOPT_MAXREDIRS, -1L);
- curl_easy_setopt (e, CURLOPT_NOSIGNAL, 1L);
- curl_easy_setopt (e, CURLOPT_PRIVATE, task);
+ bool is_default_value;
+ const tr_address * addr;
+ CURL * e = task->curl_easy = curl_easy_init ();
+
+ task->timeout_secs = getTimeoutFromURL (task);
+
+ curl_easy_setopt (e, CURLOPT_AUTOREFERER, 1L);
+ curl_easy_setopt (e, CURLOPT_COOKIEFILE, web->cookie_filename);
+ curl_easy_setopt (e, CURLOPT_ENCODING, "gzip;q=1.0, deflate, identity");
+ curl_easy_setopt (e, CURLOPT_FOLLOWLOCATION, 1L);
+ curl_easy_setopt (e, CURLOPT_MAXREDIRS, -1L);
+ curl_easy_setopt (e, CURLOPT_NOSIGNAL, 1L);
+ curl_easy_setopt (e, CURLOPT_PRIVATE, task);
#ifdef USE_LIBCURL_SOCKOPT
- curl_easy_setopt (e, CURLOPT_SOCKOPTFUNCTION, sockoptfunction);
- curl_easy_setopt (e, CURLOPT_SOCKOPTDATA, task);
+ curl_easy_setopt (e, CURLOPT_SOCKOPTFUNCTION, sockoptfunction);
+ curl_easy_setopt (e, CURLOPT_SOCKOPTDATA, task);
#endif
- if (web->curl_ssl_verify)
- curl_easy_setopt (e, CURLOPT_CAINFO, web->curl_ca_bundle);
- else {
- curl_easy_setopt (e, CURLOPT_SSL_VERIFYHOST, 0L);
- curl_easy_setopt (e, CURLOPT_SSL_VERIFYPEER, 0L);
+ if (web->curl_ssl_verify)
+ {
+ curl_easy_setopt (e, CURLOPT_CAINFO, web->curl_ca_bundle);
+ }
+ else
+ {
+ curl_easy_setopt (e, CURLOPT_SSL_VERIFYHOST, 0L);
+ curl_easy_setopt (e, CURLOPT_SSL_VERIFYPEER, 0L);
}
- curl_easy_setopt (e, CURLOPT_TIMEOUT, task->timeout_secs);
- curl_easy_setopt (e, CURLOPT_URL, task->url);
- curl_easy_setopt (e, CURLOPT_USERAGENT, TR_NAME "/" SHORT_VERSION_STRING);
- curl_easy_setopt (e, CURLOPT_VERBOSE, (long)(web->curl_verbose?1:0));
- curl_easy_setopt (e, CURLOPT_WRITEDATA, task);
- curl_easy_setopt (e, CURLOPT_WRITEFUNCTION, writeFunc);
-
- if (((addr = tr_sessionGetPublicAddress (s, TR_AF_INET, &is_default_value))) && !is_default_value)
- curl_easy_setopt (e, CURLOPT_INTERFACE, tr_address_to_string (addr));
- else if (((addr = tr_sessionGetPublicAddress (s, TR_AF_INET6, &is_default_value))) && !is_default_value)
- curl_easy_setopt (e, CURLOPT_INTERFACE, tr_address_to_string (addr));
-
- if (task->cookies != NULL)
- curl_easy_setopt (e, CURLOPT_COOKIE, task->cookies);
-
- if (task->range != NULL) {
- curl_easy_setopt (e, CURLOPT_RANGE, task->range);
- /* don't bother asking the server to compress webseed fragments */
- curl_easy_setopt (e, CURLOPT_ENCODING, "identity");
+ curl_easy_setopt (e, CURLOPT_TIMEOUT, task->timeout_secs);
+ curl_easy_setopt (e, CURLOPT_URL, task->url);
+ curl_easy_setopt (e, CURLOPT_USERAGENT, TR_NAME "/" SHORT_VERSION_STRING);
+ curl_easy_setopt (e, CURLOPT_VERBOSE, (long)(web->curl_verbose?1:0));
+ curl_easy_setopt (e, CURLOPT_WRITEDATA, task);
+ curl_easy_setopt (e, CURLOPT_WRITEFUNCTION, writeFunc);
+
+ if (((addr = tr_sessionGetPublicAddress (s, TR_AF_INET, &is_default_value))) && !is_default_value)
+ curl_easy_setopt (e, CURLOPT_INTERFACE, tr_address_to_string (addr));
+ else if (((addr = tr_sessionGetPublicAddress (s, TR_AF_INET6, &is_default_value))) && !is_default_value)
+ curl_easy_setopt (e, CURLOPT_INTERFACE, tr_address_to_string (addr));
+
+ if (task->cookies != NULL)
+ curl_easy_setopt (e, CURLOPT_COOKIE, task->cookies);
+
+ if (task->range != NULL)
+ {
+ curl_easy_setopt (e, CURLOPT_RANGE, task->range);
+ /* don't bother asking the server to compress webseed fragments */
+ curl_easy_setopt (e, CURLOPT_ENCODING, "identity");
}
- return e;
+ return e;
}
/***
static void
task_finish_func (void * vtask)
{
- struct tr_web_task * task = vtask;
- dbgmsg ("finished web task %p; got %ld", task, task->code);
-
- if (task->done_func != NULL)
- task->done_func (task->session,
- task->did_connect,
- task->did_timeout,
- task->code,
- evbuffer_pullup (task->response, -1),
- evbuffer_get_length (task->response),
- task->done_func_user_data);
-
- task_free (task);
+ struct tr_web_task * task = vtask;
+ dbgmsg ("finished web task %p; got %ld", task, task->code);
+
+ if (task->done_func != NULL)
+ task->done_func (task->session,
+ task->did_connect,
+ task->did_timeout,
+ task->code,
+ evbuffer_pullup (task->response, -1),
+ evbuffer_get_length (task->response),
+ task->done_func_user_data);
+
+ task_free (task);
}
/****
tr_web_done_func done_func,
void * done_func_user_data)
{
- return tr_webRunWithBuffer (session, url, range, cookies,
- done_func, done_func_user_data,
- NULL);
+ return tr_webRunWithBuffer (session, url, range, cookies,
+ done_func, done_func_user_data,
+ NULL);
}
struct tr_web_task *
void * done_func_user_data,
struct evbuffer * buffer)
{
- struct tr_web * web = session->web;
+ struct tr_web * web = session->web;
- if (web != NULL)
+ if (web != NULL)
{
- struct tr_web_task * task = tr_new0 (struct tr_web_task, 1);
-
- task->session = session;
- task->url = tr_strdup (url);
- task->range = tr_strdup (range);
- task->cookies = tr_strdup (cookies);
- task->done_func = done_func;
- task->done_func_user_data = done_func_user_data;
- task->response = buffer ? buffer : evbuffer_new ();
- task->freebuf = buffer ? NULL : task->response;
-
- tr_lockLock (web->taskLock);
- task->next = web->tasks;
- web->tasks = task;
- tr_lockUnlock (web->taskLock);
- return task;
+ struct tr_web_task * task = tr_new0 (struct tr_web_task, 1);
+
+ task->session = session;
+ task->url = tr_strdup (url);
+ task->range = tr_strdup (range);
+ task->cookies = tr_strdup (cookies);
+ task->done_func = done_func;
+ task->done_func_user_data = done_func_user_data;
+ task->response = buffer ? buffer : evbuffer_new ();
+ task->freebuf = buffer ? NULL : task->response;
+
+ tr_lockLock (web->taskLock);
+ task->next = web->tasks;
+ web->tasks = task;
+ tr_lockUnlock (web->taskLock);
+ return task;
}
- return NULL;
+
+ return NULL;
}
/**
struct timeval * t)
{
#ifdef WIN32
- if (!r_fd_set->fd_count && !w_fd_set->fd_count && !c_fd_set->fd_count)
+ if (!r_fd_set->fd_count && !w_fd_set->fd_count && !c_fd_set->fd_count)
{
- const long int msec = t->tv_sec*1000 + t->tv_usec/1000;
- tr_wait_msec (msec);
+ const long int msec = t->tv_sec*1000 + t->tv_usec/1000;
+ tr_wait_msec (msec);
}
- else if (select (0, r_fd_set->fd_count ? r_fd_set : NULL,
- w_fd_set->fd_count ? w_fd_set : NULL,
- c_fd_set->fd_count ? c_fd_set : NULL, t) < 0)
+ else if (select (0, r_fd_set->fd_count ? r_fd_set : NULL,
+ w_fd_set->fd_count ? w_fd_set : NULL,
+ c_fd_set->fd_count ? c_fd_set : NULL, t) < 0)
{
- char errstr[512];
- const int e = EVUTIL_SOCKET_ERROR ();
- tr_net_strerror (errstr, sizeof (errstr), e);
- dbgmsg ("Error: select (%d) %s", e, errstr);
+ char errstr[512];
+ const int e = EVUTIL_SOCKET_ERROR ();
+ tr_net_strerror (errstr, sizeof (errstr), e);
+ dbgmsg ("Error: select (%d) %s", e, errstr);
}
#else
- select (nfds, r_fd_set, w_fd_set, c_fd_set, t);
+ select (nfds, r_fd_set, w_fd_set, c_fd_set, t);
#endif
}
static void
tr_webThreadFunc (void * vsession)
{
- CURLM * multi;
- struct tr_web * web;
- int taskCount = 0;
- struct tr_web_task * task;
- tr_session * session = vsession;
-
- /* try to enable ssl for https support; but if that fails,
- * try a plain vanilla init */
- if (curl_global_init (CURL_GLOBAL_SSL))
- curl_global_init (0);
-
- web = tr_new0 (struct tr_web, 1);
- web->close_mode = ~0;
- web->taskLock = tr_lockNew ();
- web->tasks = NULL;
- web->curl_verbose = getenv ("TR_CURL_VERBOSE") != NULL;
- web->curl_ssl_verify = getenv ("TR_CURL_SSL_VERIFY") != NULL;
- web->curl_ca_bundle = getenv ("CURL_CA_BUNDLE");
- if (web->curl_ssl_verify) {
- tr_ninf ("web", "will verify tracker certs using envvar CURL_CA_BUNDLE: %s",
- web->curl_ca_bundle == NULL ? "none" : web->curl_ca_bundle);
- tr_ninf ("web", "NB: this only works if you built against libcurl with openssl or gnutls, NOT nss");
- tr_ninf ("web", "NB: invalid certs will show up as 'Could not connect to tracker' like many other errors");
+ CURLM * multi;
+ struct tr_web * web;
+ int taskCount = 0;
+ struct tr_web_task * task;
+ tr_session * session = vsession;
+
+ /* try to enable ssl for https support; but if that fails,
+ * try a plain vanilla init */
+ if (curl_global_init (CURL_GLOBAL_SSL))
+ curl_global_init (0);
+
+ web = tr_new0 (struct tr_web, 1);
+ web->close_mode = ~0;
+ web->taskLock = tr_lockNew ();
+ web->tasks = NULL;
+ web->curl_verbose = getenv ("TR_CURL_VERBOSE") != NULL;
+ web->curl_ssl_verify = getenv ("TR_CURL_SSL_VERIFY") != NULL;
+ web->curl_ca_bundle = getenv ("CURL_CA_BUNDLE");
+ if (web->curl_ssl_verify)
+ {
+ tr_ninf ("web", "will verify tracker certs using envvar CURL_CA_BUNDLE: %s",
+ web->curl_ca_bundle == NULL ? "none" : web->curl_ca_bundle);
+ tr_ninf ("web", "NB: this only works if you built against libcurl with openssl or gnutls, NOT nss");
+ tr_ninf ("web", "NB: invalid certs will show up as 'Could not connect to tracker' like many other errors");
}
- web->cookie_filename = tr_buildPath (session->configDir, "cookies.txt", NULL);
+ web->cookie_filename = tr_buildPath (session->configDir, "cookies.txt", NULL);
- multi = curl_multi_init ();
- session->web = web;
+ multi = curl_multi_init ();
+ session->web = web;
- for (;;)
+ for (;;)
{
- long msec;
- int unused;
- CURLMsg * msg;
- CURLMcode mcode;
-
- if (web->close_mode == TR_WEB_CLOSE_NOW)
- break;
- if ((web->close_mode == TR_WEB_CLOSE_WHEN_IDLE) && (web->tasks == NULL))
- break;
-
- /* add tasks from the queue */
- tr_lockLock (web->taskLock);
- while (web->tasks != NULL)
+ long msec;
+ int unused;
+ CURLMsg * msg;
+ CURLMcode mcode;
+
+ if (web->close_mode == TR_WEB_CLOSE_NOW)
+ break;
+ if ((web->close_mode == TR_WEB_CLOSE_WHEN_IDLE) && (web->tasks == NULL))
+ break;
+
+ /* add tasks from the queue */
+ tr_lockLock (web->taskLock);
+ while (web->tasks != NULL)
{
- /* pop the task */
- task = web->tasks;
- web->tasks = task->next;
- task->next = NULL;
-
- dbgmsg ("adding task to curl: [%s]", task->url);
- curl_multi_add_handle (multi, createEasy (session, web, task));
- /*fprintf (stderr, "adding a task.. taskCount is now %d\n", taskCount);*/
- ++taskCount;
+ /* pop the task */
+ task = web->tasks;
+ web->tasks = task->next;
+ task->next = NULL;
+
+ dbgmsg ("adding task to curl: [%s]", task->url);
+ curl_multi_add_handle (multi, createEasy (session, web, task));
+ /*fprintf (stderr, "adding a task.. taskCount is now %d\n", taskCount);*/
+ ++taskCount;
}
- tr_lockUnlock (web->taskLock);
-
- /* maybe wait a little while before calling curl_multi_perform () */
- msec = 0;
- curl_multi_timeout (multi, &msec);
- if (msec < 0)
- msec = THREADFUNC_MAX_SLEEP_MSEC;
- if (session->isClosed)
- msec = 100; /* on shutdown, call perform () more frequently */
- if (msec > 0)
+ tr_lockUnlock (web->taskLock);
+
+ /* maybe wait a little while before calling curl_multi_perform () */
+ msec = 0;
+ curl_multi_timeout (multi, &msec);
+ if (msec < 0)
+ msec = THREADFUNC_MAX_SLEEP_MSEC;
+ if (session->isClosed)
+ msec = 100; /* on shutdown, call perform () more frequently */
+ if (msec > 0)
{
- int usec;
- int max_fd;
- struct timeval t;
- fd_set r_fd_set, w_fd_set, c_fd_set;
-
- max_fd = 0;
- FD_ZERO (&r_fd_set);
- FD_ZERO (&w_fd_set);
- FD_ZERO (&c_fd_set);
- curl_multi_fdset (multi, &r_fd_set, &w_fd_set, &c_fd_set, &max_fd);
-
- if (msec > THREADFUNC_MAX_SLEEP_MSEC)
- msec = THREADFUNC_MAX_SLEEP_MSEC;
-
- usec = msec * 1000;
- t.tv_sec = usec / 1000000;
- t.tv_usec = usec % 1000000;
- tr_select (max_fd+1, &r_fd_set, &w_fd_set, &c_fd_set, &t);
+ int usec;
+ int max_fd;
+ struct timeval t;
+ fd_set r_fd_set, w_fd_set, c_fd_set;
+
+ max_fd = 0;
+ FD_ZERO (&r_fd_set);
+ FD_ZERO (&w_fd_set);
+ FD_ZERO (&c_fd_set);
+ curl_multi_fdset (multi, &r_fd_set, &w_fd_set, &c_fd_set, &max_fd);
+
+ if (msec > THREADFUNC_MAX_SLEEP_MSEC)
+ msec = THREADFUNC_MAX_SLEEP_MSEC;
+
+ usec = msec * 1000;
+ t.tv_sec = usec / 1000000;
+ t.tv_usec = usec % 1000000;
+ tr_select (max_fd+1, &r_fd_set, &w_fd_set, &c_fd_set, &t);
}
- /* call curl_multi_perform () */
- do {
- mcode = curl_multi_perform (multi, &unused);
- } while (mcode == CURLM_CALL_MULTI_PERFORM);
+ /* call curl_multi_perform () */
+ do
+ mcode = curl_multi_perform (multi, &unused);
+ while (mcode == CURLM_CALL_MULTI_PERFORM);
- /* pump completed tasks from the multi */
- while ((msg = curl_multi_info_read (multi, &unused)))
+ /* pump completed tasks from the multi */
+ while ((msg = curl_multi_info_read (multi, &unused)))
{
- if ((msg->msg == CURLMSG_DONE) && (msg->easy_handle != NULL))
+ if ((msg->msg == CURLMSG_DONE) && (msg->easy_handle != NULL))
{
- double total_time;
- struct tr_web_task * task;
- long req_bytes_sent;
- CURL * e = msg->easy_handle;
- curl_easy_getinfo (e, CURLINFO_PRIVATE, (void*)&task);
- curl_easy_getinfo (e, CURLINFO_RESPONSE_CODE, &task->code);
- curl_easy_getinfo (e, CURLINFO_REQUEST_SIZE, &req_bytes_sent);
- curl_easy_getinfo (e, CURLINFO_TOTAL_TIME, &total_time);
- task->did_connect = task->code>0 || req_bytes_sent>0;
- task->did_timeout = !task->code && (total_time >= task->timeout_secs);
- curl_multi_remove_handle (multi, e);
- curl_easy_cleanup (e);
-/*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));*/
- tr_runInEventThread (task->session, task_finish_func, task);
- --taskCount;
+ double total_time;
+ struct tr_web_task * task;
+ long req_bytes_sent;
+ CURL * e = msg->easy_handle;
+ curl_easy_getinfo (e, CURLINFO_PRIVATE, (void*)&task);
+ curl_easy_getinfo (e, CURLINFO_RESPONSE_CODE, &task->code);
+ curl_easy_getinfo (e, CURLINFO_REQUEST_SIZE, &req_bytes_sent);
+ curl_easy_getinfo (e, CURLINFO_TOTAL_TIME, &total_time);
+ task->did_connect = task->code>0 || req_bytes_sent>0;
+ task->did_timeout = !task->code && (total_time >= task->timeout_secs);
+ curl_multi_remove_handle (multi, e);
+ curl_easy_cleanup (e);
+ tr_runInEventThread (task->session, task_finish_func, task);
+ --taskCount;
}
}
}
- /* Discard any remaining tasks.
- * This is rare, but can happen on shutdown with unresponsive trackers. */
- while (web->tasks != NULL) {
- task = web->tasks;
- web->tasks = task->next;
- dbgmsg ("Discarding task \"%s\"", task->url);
- task_free (task);
+ /* Discard any remaining tasks.
+ * This is rare, but can happen on shutdown with unresponsive trackers. */
+ while (web->tasks != NULL)
+ {
+ task = web->tasks;
+ web->tasks = task->next;
+ dbgmsg ("Discarding task \"%s\"", task->url);
+ task_free (task);
}
- /* cleanup */
- curl_multi_cleanup (multi);
- tr_lockFree (web->taskLock);
- tr_free (web->cookie_filename);
- tr_free (web);
- session->web = NULL;
+ /* cleanup */
+ curl_multi_cleanup (multi);
+ tr_lockFree (web->taskLock);
+ tr_free (web->cookie_filename);
+ tr_free (web);
+ session->web = NULL;
}
void
tr_webInit (tr_session * session)
{
- tr_threadNew (tr_webThreadFunc, session);
+ tr_threadNew (tr_webThreadFunc, session);
}
void
tr_webClose (tr_session * session, tr_web_close_mode close_mode)
{
- if (session->web != NULL)
+ if (session->web != NULL)
{
- session->web->close_mode = close_mode;
+ session->web->close_mode = close_mode;
- if (close_mode == TR_WEB_CLOSE_NOW)
- while (session->web != NULL)
- tr_wait_msec (100);
+ if (close_mode == TR_WEB_CLOSE_NOW)
+ while (session->web != NULL)
+ tr_wait_msec (100);
}
}
void
tr_webGetTaskInfo (struct tr_web_task * task, tr_web_task_info info, void * dst)
{
- curl_easy_getinfo (task->curl_easy, (CURLINFO) info, dst);
+ curl_easy_getinfo (task->curl_easy, (CURLINFO) info, dst);
}
/*****
const char *
tr_webGetResponseStr (long code)
{
- switch (code)
+ switch (code)
{
- case 0: return "No Response";
- case 101: return "Switching Protocols";
- case 200: return "OK";
- case 201: return "Created";
- case 202: return "Accepted";
- case 203: return "Non-Authoritative Information";
- case 204: return "No Content";
- case 205: return "Reset Content";
- case 206: return "Partial Content";
- case 300: return "Multiple Choices";
- case 301: return "Moved Permanently";
- case 302: return "Found";
- case 303: return "See Other";
- case 304: return "Not Modified";
- case 305: return "Use Proxy";
- case 306: return " (Unused)";
- case 307: return "Temporary Redirect";
- case 400: return "Bad Request";
- case 401: return "Unauthorized";
- case 402: return "Payment Required";
- case 403: return "Forbidden";
- case 404: return "Not Found";
- case 405: return "Method Not Allowed";
- case 406: return "Not Acceptable";
- case 407: return "Proxy Authentication Required";
- case 408: return "Request Timeout";
- case 409: return "Conflict";
- case 410: return "Gone";
- case 411: return "Length Required";
- case 412: return "Precondition Failed";
- case 413: return "Request Entity Too Large";
- case 414: return "Request-URI Too Long";
- case 415: return "Unsupported Media Type";
- case 416: return "Requested Range Not Satisfiable";
- case 417: return "Expectation Failed";
- case 500: return "Internal Server Error";
- case 501: return "Not Implemented";
- case 502: return "Bad Gateway";
- case 503: return "Service Unavailable";
- case 504: return "Gateway Timeout";
- case 505: return "HTTP Version Not Supported";
- default: return "Unknown Error";
+ case 0: return "No Response";
+ case 101: return "Switching Protocols";
+ case 200: return "OK";
+ case 201: return "Created";
+ case 202: return "Accepted";
+ case 203: return "Non-Authoritative Information";
+ case 204: return "No Content";
+ case 205: return "Reset Content";
+ case 206: return "Partial Content";
+ case 300: return "Multiple Choices";
+ case 301: return "Moved Permanently";
+ case 302: return "Found";
+ case 303: return "See Other";
+ case 304: return "Not Modified";
+ case 305: return "Use Proxy";
+ case 306: return " (Unused)";
+ case 307: return "Temporary Redirect";
+ case 400: return "Bad Request";
+ case 401: return "Unauthorized";
+ case 402: return "Payment Required";
+ case 403: return "Forbidden";
+ case 404: return "Not Found";
+ case 405: return "Method Not Allowed";
+ case 406: return "Not Acceptable";
+ case 407: return "Proxy Authentication Required";
+ case 408: return "Request Timeout";
+ case 409: return "Conflict";
+ case 410: return "Gone";
+ case 411: return "Length Required";
+ case 412: return "Precondition Failed";
+ case 413: return "Request Entity Too Large";
+ case 414: return "Request-URI Too Long";
+ case 415: return "Unsupported Media Type";
+ case 416: return "Requested Range Not Satisfiable";
+ case 417: return "Expectation Failed";
+ case 500: return "Internal Server Error";
+ case 501: return "Not Implemented";
+ case 502: return "Bad Gateway";
+ case 503: return "Service Unavailable";
+ case 504: return "Gateway Timeout";
+ case 505: return "HTTP Version Not Supported";
+ default: return "Unknown Error";
}
}
void
tr_http_escape (struct evbuffer * out,
- const char * str, int len, bool escape_slashes)
+ const char * str,
+ int len,
+ bool escape_slashes)
{
- const char * end;
-
- if ((len < 0) && (str != NULL))
- len = strlen (str);
-
- for (end=str+len; str && str!=end; ++str) {
- if ((*str == ',')
- || (*str == '-')
- || (*str == '.')
- || (('0' <= *str) && (*str <= '9'))
- || (('A' <= *str) && (*str <= 'Z'))
- || (('a' <= *str) && (*str <= 'z'))
- || ((*str == '/') && (!escape_slashes)))
- evbuffer_add_printf (out, "%c", *str);
- else
- evbuffer_add_printf (out, "%%%02X", (unsigned)(*str&0xFF));
+ const char * end;
+
+ if ((len < 0) && (str != NULL))
+ len = strlen (str);
+
+ for (end=str+len; str && str!=end; ++str)
+ {
+ if ((*str == ',') || (*str == '-')
+ || (*str == '.')
+ || (('0' <= *str) && (*str <= '9'))
+ || (('A' <= *str) && (*str <= 'Z'))
+ || (('a' <= *str) && (*str <= 'z'))
+ || ((*str == '/') && (!escape_slashes)))
+ evbuffer_add_printf (out, "%c", *str);
+ else
+ evbuffer_add_printf (out, "%%%02X", (unsigned)(*str&0xFF));
}
}
char *
tr_http_unescape (const char * str, int len)
{
- char * tmp = curl_unescape (str, len);
- char * ret = tr_strdup (tmp);
- curl_free (tmp);
- return ret;
+ char * tmp = curl_unescape (str, len);
+ char * ret = tr_strdup (tmp);
+ curl_free (tmp);
+ return ret;
}
static int
is_rfc2396_alnum (uint8_t ch)
{
- return ('0' <= ch && ch <= '9')
- || ('A' <= ch && ch <= 'Z')
- || ('a' <= ch && ch <= 'z')
- || ch == '.'
- || ch == '-'
- || ch == '_'
- || ch == '~';
+ return ('0' <= ch && ch <= '9')
+ || ('A' <= ch && ch <= 'Z')
+ || ('a' <= ch && ch <= 'z')
+ || ch == '.'
+ || ch == '-'
+ || ch == '_'
+ || ch == '~';
}
void
tr_http_escape_sha1 (char * out, const uint8_t * sha1_digest)
{
- const uint8_t * in = sha1_digest;
- const uint8_t * end = in + SHA_DIGEST_LENGTH;
+ const uint8_t * in = sha1_digest;
+ const uint8_t * end = in + SHA_DIGEST_LENGTH;
- while (in != end)
- if (is_rfc2396_alnum (*in))
- *out++ = (char) *in++;
- else
- out += tr_snprintf (out, 4, "%%%02x", (unsigned int)*in++);
+ while (in != end)
+ if (is_rfc2396_alnum (*in))
+ *out++ = (char) *in++;
+ else
+ out += tr_snprintf (out, 4, "%%%02x", (unsigned int)*in++);
- *out = '\0';
+ *out = '\0';
}