From 1f2bccd17bbbfbbd6707704348b7892f7dca961a Mon Sep 17 00:00:00 2001 From: Jordan Lee Date: Sat, 2 Feb 2013 13:42:50 +0000 Subject: [PATCH] (libT) recycle the peer id used for public torrents after N hours of use --- libtransmission/announcer.c | 8 +++--- libtransmission/handshake.c | 12 ++++----- libtransmission/quark.c | 1 + libtransmission/quark.h | 1 + libtransmission/session.c | 6 ++++- libtransmission/session.h | 2 ++ libtransmission/torrent.c | 51 ++++++++++++++++++++++++++++++++++--- libtransmission/torrent.h | 7 ++++- 8 files changed, 71 insertions(+), 17 deletions(-) diff --git a/libtransmission/announcer.c b/libtransmission/announcer.c index 9d27e7d02..af03c42b8 100644 --- a/libtransmission/announcer.c +++ b/libtransmission/announcer.c @@ -905,7 +905,7 @@ tr_announcerAddBytes (tr_torrent * tor, int type, uint32_t byteCount) static tr_announce_request * announce_request_new (const tr_announcer * announcer, - const tr_torrent * tor, + tr_torrent * tor, const tr_tier * tier, tr_announce_event event) { @@ -914,7 +914,7 @@ announce_request_new (const tr_announcer * announcer, req->url = tr_strdup (tier->currentTracker->announce); req->tracker_id_str = tr_strdup (tier->currentTracker->tracker_id_str); memcpy (req->info_hash, tor->info.hash, SHA_DIGEST_LENGTH); - memcpy (req->peer_id, tor->peer_id, PEER_ID_LEN); + memcpy (req->peer_id, tr_torrentGetPeerId(tor), PEER_ID_LEN); req->up = tier->byteCounts[TR_ANN_UP]; req->down = tier->byteCounts[TR_ANN_DOWN]; req->corrupt = tier->byteCounts[TR_ANN_CORRUPT]; @@ -1209,7 +1209,7 @@ announce_request_delegate (tr_announcer * announcer, #if 0 fprintf (stderr, "ANNOUNCE: event %s isPartialSeed %d port %d key %d numwant %d" " up %"PRIu64" down %"PRIu64" corrupt %"PRIu64" left %"PRIu64 - " url [%s] tracker_id_str [%s] peer_id [%8.8s]\n", + " url [%s] tracker_id_str [%s] peer_id [%20.20s]\n", tr_announce_event_get_string (request->event), (int)request->partial_seed, (int)request->port, @@ -1240,7 +1240,7 @@ tierAnnounce (tr_announcer * announcer, tr_tier * tier) tr_announce_event announce_event; tr_announce_request * req; struct announce_data * data; - const tr_torrent * tor = tier->tor; + tr_torrent * tor = tier->tor; const time_t now = tr_time (); assert (!tier->isAnnouncing); diff --git a/libtransmission/handshake.c b/libtransmission/handshake.c index 6ada2127e..87799b0d4 100644 --- a/libtransmission/handshake.c +++ b/libtransmission/handshake.c @@ -193,8 +193,8 @@ buildHandshakeMessage (tr_handshake * handshake, uint8_t * buf) { uint8_t * walk = buf; const uint8_t * torrentHash = tr_cryptoGetTorrentHash (handshake->crypto); - const tr_torrent * tor = tr_torrentFindFromHash (handshake->session, torrentHash); - const uint8_t * peer_id = tor->peer_id; + tr_torrent * tor = tr_torrentFindFromHash (handshake->session, torrentHash); + const unsigned char * peer_id = tr_torrentGetPeerId (tor); memcpy (walk, HANDSHAKE_NAME, HANDSHAKE_NAME_LEN); walk += HANDSHAKE_NAME_LEN; @@ -235,8 +235,7 @@ parseHandshake (tr_handshake * handshake, uint8_t name[HANDSHAKE_NAME_LEN]; uint8_t reserved[HANDSHAKE_FLAGS_LEN]; uint8_t hash[SHA_DIGEST_LENGTH]; - const tr_torrent * tor; - const uint8_t * tor_peer_id; + tr_torrent * tor; uint8_t peer_id[PEER_ID_LEN]; dbgmsg (handshake, "payload: need %d, got %zu", @@ -272,8 +271,7 @@ parseHandshake (tr_handshake * handshake, dbgmsg (handshake, "peer-id is [%*.*s]", PEER_ID_LEN, PEER_ID_LEN, peer_id); tor = tr_torrentFindFromHash (handshake->session, hash); - tor_peer_id = tor->peer_id; - if (!memcmp (peer_id, tor_peer_id, PEER_ID_LEN)) + if (!memcmp (peer_id, tr_torrentGetPeerId(tor), PEER_ID_LEN)) { dbgmsg (handshake, "streuth! we've connected to ourselves."); return HANDSHAKE_PEER_IS_SELF; @@ -703,7 +701,7 @@ readPeerId (tr_handshake * handshake, /* if we've somehow connected to ourselves, don't keep the connection */ tor = tr_torrentFindFromHash (handshake->session, tr_peerIoGetTorrentHash (handshake->io)); - connected_to_self = (tor != NULL) && !memcmp (peer_id, tor->peer_id, PEER_ID_LEN); + connected_to_self = (tor != NULL) && !memcmp (peer_id, tr_torrentGetPeerId(tor), PEER_ID_LEN); return tr_handshakeDone (handshake, !connected_to_self); } diff --git a/libtransmission/quark.c b/libtransmission/quark.c index ce18f20b9..d15f4ace3 100644 --- a/libtransmission/quark.c +++ b/libtransmission/quark.c @@ -208,6 +208,7 @@ static const struct tr_key_struct my_static[] = { "paused", 6 }, { "pausedTorrentCount", 18 }, { "peer-congestion-algorithm", 25 }, + { "peer-id-ttl-hours", 17 }, { "peer-limit", 10 }, { "peer-limit-global", 17 }, { "peer-limit-per-torrent", 22 }, diff --git a/libtransmission/quark.h b/libtransmission/quark.h index 25ea00378..39fcd5393 100644 --- a/libtransmission/quark.h +++ b/libtransmission/quark.h @@ -218,6 +218,7 @@ enum TR_KEY_paused, TR_KEY_pausedTorrentCount, TR_KEY_peer_congestion_algorithm, + TR_KEY_peer_id_ttl_hours, TR_KEY_peer_limit, TR_KEY_peer_limit_global, TR_KEY_peer_limit_per_torrent, diff --git a/libtransmission/session.c b/libtransmission/session.c index 9caaba96e..418f95468 100644 --- a/libtransmission/session.c +++ b/libtransmission/session.c @@ -308,7 +308,7 @@ tr_sessionGetDefaultSettings (tr_variant * d) { assert (tr_variantIsDict (d)); - tr_variantDictReserve (d, 62); + tr_variantDictReserve (d, 63); tr_variantDictAddBool (d, TR_KEY_blocklist_enabled, false); tr_variantDictAddStr (d, TR_KEY_blocklist_url, "http://www.example.com/blocklist"); tr_variantDictAddInt (d, TR_KEY_cache_size_mb, DEFAULT_CACHE_SIZE_MB); @@ -337,6 +337,7 @@ tr_sessionGetDefaultSettings (tr_variant * d) tr_variantDictAddBool (d, TR_KEY_port_forwarding_enabled, true); tr_variantDictAddInt (d, TR_KEY_preallocation, TR_PREALLOCATE_SPARSE); tr_variantDictAddBool (d, TR_KEY_prefetch_enabled, DEFAULT_PREFETCH_ENABLED); + tr_variantDictAddInt (d, TR_KEY_peer_id_ttl_hours, 6); tr_variantDictAddBool (d, TR_KEY_queue_stalled_enabled, true); tr_variantDictAddInt (d, TR_KEY_queue_stalled_minutes, 30); tr_variantDictAddReal (d, TR_KEY_ratio_limit, 2.0); @@ -408,6 +409,7 @@ tr_sessionGetSettings (tr_session * s, tr_variant * d) tr_variantDictAddBool (d, TR_KEY_port_forwarding_enabled, tr_sessionIsPortForwardingEnabled (s)); tr_variantDictAddInt (d, TR_KEY_preallocation, s->preallocationMode); tr_variantDictAddInt (d, TR_KEY_prefetch_enabled, s->isPrefetchEnabled); + tr_variantDictAddInt (d, TR_KEY_peer_id_ttl_hours, s->peer_id_ttl_hours); tr_variantDictAddBool (d, TR_KEY_queue_stalled_enabled, tr_sessionGetQueueStalledEnabled (s)); tr_variantDictAddInt (d, TR_KEY_queue_stalled_minutes, tr_sessionGetQueueStalledMinutes (s)); tr_variantDictAddReal (d, TR_KEY_ratio_limit, s->desiredRatio); @@ -799,6 +801,8 @@ sessionSetImpl (void * vdata) tr_sessionSetPaused (session, !boolVal); if (tr_variantDictFindBool (settings, TR_KEY_trash_original_torrent_files, &boolVal)) tr_sessionSetDeleteSource (session, boolVal); + if (tr_variantDictFindInt (settings, TR_KEY_peer_id_ttl_hours, &i)) + session->peer_id_ttl_hours = i; /* torrent queues */ if (tr_variantDictFindInt (settings, TR_KEY_queue_stalled_minutes, &i)) diff --git a/libtransmission/session.h b/libtransmission/session.h index 6ea3a334f..780f1454a 100644 --- a/libtransmission/session.h +++ b/libtransmission/session.h @@ -118,6 +118,8 @@ struct tr_session bool deleteSourceTorrent; bool scrapePausedTorrents; + uint8_t peer_id_ttl_hours; + tr_variant removedTorrents; bool stalledEnabled; diff --git a/libtransmission/torrent.c b/libtransmission/torrent.c index ee6da4927..9ca66e75f 100644 --- a/libtransmission/torrent.c +++ b/libtransmission/torrent.c @@ -174,6 +174,51 @@ tr_torrentIsPieceTransferAllowed (const tr_torrent * tor, return allowed; } +/*** +**** +***/ + +static void +tr_torrentUnsetPeerId (tr_torrent * tor) +{ + /* triggers a rebuild next time tr_torrentGetPeerId() is called */ + *tor->peer_id = '\0'; +} + +static int +peerIdTTL (const tr_torrent * tor) +{ + int ttl; + + if (!tor->peer_id_creation_time) + ttl = 0; + else + ttl = (int)difftime(tor->peer_id_creation_time+(tor->session->peer_id_ttl_hours*3600), tr_time()); + + return ttl; +} + +const unsigned char * +tr_torrentGetPeerId (tr_torrent * tor) +{ + bool needs_new_peer_id = false; + + if (!*tor->peer_id) + needs_new_peer_id = true; + + if (!needs_new_peer_id) + if (!tr_torrentIsPrivate (tor)) + if (peerIdTTL (tor) <= 0) + needs_new_peer_id = true; + + if (needs_new_peer_id) + { + tr_peerIdInit (tor->peer_id); + tor->peer_id_creation_time = tr_time (); + } + + return tor->peer_id; +} /*** **** PER-TORRENT UL / DL SPEEDS ***/ @@ -820,8 +865,6 @@ torrentInit (tr_torrent * tor, const tr_ctor * ctor) tor->magicNumber = TORRENT_MAGIC_NUMBER; tor->queuePosition = session->torrentCount; - tr_peerIdInit (tor->peer_id); - tr_sha1 (tor->obfuscatedHash, "req2", 4, tor->info.hash, SHA_DIGEST_LENGTH, NULL); @@ -1660,8 +1703,8 @@ torrentStart (tr_torrent * tor, bool bypass_queue) * closed and opened again without quitting Transmission ... * change the peerid. It would help sometimes if a stopped event * was missed to ensure that we didn't think someone was cheating. */ - tr_peerIdInit (tor->peer_id); - tor->isRunning = 1; + tr_torrentUnsetPeerId (tor); + tor->isRunning = true; tr_torrentSetDirty (tor); tr_runInEventThread (tor->session, torrentStartImpl, tor); diff --git a/libtransmission/torrent.h b/libtransmission/torrent.h index 2be535e5e..5bbe16782 100644 --- a/libtransmission/torrent.h +++ b/libtransmission/torrent.h @@ -159,7 +159,9 @@ struct tr_torrent * peer_id that was registered by the peer. The peer_id from the tracker * and in the handshake are expected to match. */ - uint8_t peer_id[PEER_ID_LEN+1]; + unsigned char peer_id[PEER_ID_LEN+1]; + + time_t peer_id_creation_time; /* Where the files will be when it's complete */ char * downloadDir; @@ -435,6 +437,9 @@ uint64_t tr_torrentGetCurrentSizeOnDisk (const tr_torrent * tor); bool tr_torrentIsStalled (const tr_torrent * tor); +const unsigned char * tr_torrentGetPeerId (tr_torrent * tor); + + static inline bool tr_torrentIsQueued (const tr_torrent * tor) {