1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2025-03-15 16:29:34 +00:00

ban peers that feed us too many bad blocks.

This commit is contained in:
Charles Kerr 2007-10-08 01:31:27 +00:00
parent 43a016cdb9
commit 161ff6a7a2
2 changed files with 71 additions and 13 deletions

View file

@ -36,6 +36,10 @@ typedef struct tr_peer
unsigned int clientIsInterested : 1;
unsigned int doPurge : 1;
/* number of bad pieces they've contributed to */
uint8_t strikes;
uint8_t encryption_preference;
uint16_t port;
struct in_addr in_addr;

View file

@ -68,9 +68,13 @@ enum
/* corresponds to ut_pex's added.f flags */
ADDED_F_ENCRYPTION_FLAG = 1,
/* corresponds to ut_pex's added.f flags */
ADDED_F_SEED_FLAG = 2
ADDED_F_SEED_FLAG = 2,
/* number of bad pieces a peer is allowed to send before we ban them */
MAX_BAD_PIECES_PER_PEER = 3,
/* use for bitwise operations w/peer_atom.myflags */
MYFLAG_BANNED = 1
};
@ -86,6 +90,7 @@ struct peer_atom
{
uint8_t from;
uint8_t flags; /* these match the added_f flags */
uint8_t myflags; /* flags that aren't defined in added_f */
uint16_t port;
struct in_addr addr;
time_t time;
@ -340,7 +345,6 @@ peerDestructor( tr_peer * peer )
tr_bitfieldFree( peer->have );
tr_bitfieldFree( peer->blame );
tr_bitfieldFree( peer->banned );
tr_rcClose( peer->rcToClient );
tr_rcClose( peer->rcToPeer );
tr_free( peer->client );
@ -908,16 +912,28 @@ myHandshakeDoneCB( tr_handshake * handshake,
}
else /* looking good */
{
tr_peer * peer = getPeer( t, in_addr );
uint16_t port;
const struct in_addr * addr = tr_peerIoGetAddress( io, &port );
struct peer_atom * atom;
ensureAtomExists( t, addr, port, 0, TR_PEER_FROM_INCOMING );
tr_free( peer->client );
peer->client = peer_id ? tr_clientForId( peer_id ) : NULL;
if( peer->msgs != NULL ) { /* we already have this peer */
atom = getExistingAtom( t, addr );
tr_peer * peer = getPeer( t, addr );
if( atom->myflags & MYFLAG_BANNED )
{
tordbg( t, "banned peer %s tried to reconnect", tr_peerIoAddrStr(&atom->addr,atom->port) );
tr_peerIoFree( io );
--manager->connectionCount;
} else {
peer->doPurge = 1;
}
else if( peer->msgs != NULL ) /* we already have this peer */
{
tr_peerIoFree( io );
--manager->connectionCount;
}
else
{
tr_free( peer->client );
peer->client = peer_id ? tr_clientForId( peer_id ) : NULL;
peer->port = port;
peer->io = io;
peer->msgs = tr_peerMsgsNew( t->tor, peer, msgsCallbackFunc, t, &peer->msgsTag );
@ -1002,12 +1018,42 @@ tr_peerMgrAddPeers( tr_peerMgr * manager,
**/
void
tr_peerMgrSetBlame( tr_peerMgr * manager UNUSED,
const uint8_t * torrentHash UNUSED,
int pieceIndex UNUSED,
int success UNUSED )
tr_peerMgrSetBlame( tr_peerMgr * manager,
const uint8_t * torrentHash,
int pieceIndex,
int success )
{
/*fprintf( stderr, "FIXME: tr_peerMgrSetBlame\n" );*/
if( !success )
{
int peerCount, i;
Torrent * t = getExistingTorrent( manager, torrentHash );
tr_peer ** peers;
assert( torrentIsLocked( t ) );
peers = (tr_peer **) tr_ptrArrayPeek( t->peers, &peerCount );
for( i=0; i<peerCount; ++i )
{
struct peer_atom * atom;
tr_peer * peer;
peer = peers[i];
if( !tr_bitfieldHas( peer->blame, pieceIndex ) )
continue;
++peer->strikes;
tordbg( t, "peer %s contributed to corrupt piece (%d); now has %d strikes",
tr_peerIoAddrStr(&peer->in_addr,peer->port),
pieceIndex, (int)peer->strikes );
if( peer->strikes < MAX_BAD_PIECES_PER_PEER )
continue;
peer->doPurge = 1;
atom = getExistingAtom( t, &peer->in_addr );
atom->myflags |= MYFLAG_BANNED;
tordbg( t, "banning peer %s due to corrupt data", tr_peerIoAddrStr(&atom->addr,atom->port) );
}
}
}
int
@ -1511,6 +1557,14 @@ getPeerCandidates( Torrent * t, int * setmeSize )
{
struct peer_atom * atom = atoms[i];
/* peer fed us too much bad data ... we only keep it around
* now to weed it out in case someone sends it to us via pex */
if( atom->myflags & MYFLAG_BANNED ) {
tordbg( t, "RECONNECT peer %d (%s) is banned...",
i, tr_peerIoAddrStr(&atom->addr,atom->port) );
continue;
}
/* we don't need two connections to the same peer... */
if( peerIsInUse( t, &atom->addr ) ) {
tordbg( t, "RECONNECT peer %d (%s) is in use..",