]> granicus.if.org Git - transmission/commitdiff
(libT) allow custom blocklists... now all you need to do is place a file in the block...
authorCharles Kerr <charles@transmissionbt.com>
Wed, 11 Jun 2008 16:15:45 +0000 (16:15 +0000)
committerCharles Kerr <charles@transmissionbt.com>
Wed, 11 Jun 2008 16:15:45 +0000 (16:15 +0000)
libtransmission/blocklist.c
libtransmission/blocklist.h
libtransmission/peer-mgr.c
libtransmission/rpc-test.c
libtransmission/session.c
libtransmission/session.h
libtransmission/transmission.h
libtransmission/utils-test.c
libtransmission/utils.c
libtransmission/utils.h

index 68a9709e36dc77f0008c2abb7ce1f6f2ef8c6fe0..1007bfeb814428fc8d2a0406162974e151b3f48b 100644 (file)
@@ -14,6 +14,7 @@
 #include <stdlib.h> /* free */
 #include <string.h>
 
+#include <libgen.h> /* basename */
 #include <sys/mman.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -89,7 +90,14 @@ blocklistLoad( tr_blocklist * b )
     b->byteCount = st.st_size;
     b->ruleCount = st.st_size / sizeof( struct tr_ip_range );
     b->fd = fd;
-    tr_inf( _( "Blocklist contains %'u entries" ), (unsigned int)b->ruleCount );
+
+    {
+        char * name;
+        char buf[MAX_PATH_LENGTH];
+        tr_strlcpy( buf, b->filename, sizeof( buf ) );
+        name = basename( buf );
+        tr_inf( _( "Blocklist \"%s\" contains %'u entries" ), name, (unsigned int)b->ruleCount );
+    }
 }
 
 static void
@@ -133,6 +141,12 @@ _tr_blocklistNew( const char * filename, int isEnabled )
     return b;
 }
 
+const char*
+_tr_blocklistGetFilename( const tr_blocklist * b )
+{
+    return b->filename;
+}
+
 void
 _tr_blocklistFree( tr_blocklist * b )
 {
@@ -142,9 +156,16 @@ _tr_blocklistFree( tr_blocklist * b )
 }
 
 int
-_tr_blocklistGetRuleCount( tr_blocklist * b )
+_tr_blocklistExists( const tr_blocklist * b )
 {
-    blocklistEnsureLoaded( b );
+    struct stat st;
+    return !stat( b->filename, &st );
+}
+
+int
+_tr_blocklistGetRuleCount( const tr_blocklist * b )
+{
+    blocklistEnsureLoaded( (tr_blocklist*)b );
 
     return b->ruleCount;
 }
@@ -185,13 +206,6 @@ _tr_blocklistHasAddress( tr_blocklist * b, const struct in_addr * addr )
     return range != NULL;
 }
 
-int
-_tr_blocklistExists( const tr_blocklist * b )
-{
-    struct stat st;
-    return !stat( b->filename, &st );
-}
-
 int
 _tr_blocklistSetContent( tr_blocklist * b,
                          const char   * filename )
@@ -255,7 +269,14 @@ _tr_blocklistSetContent( tr_blocklist * b,
         ++lineCount;
     }
 
-    tr_inf( _( "Blocklist updated with %'d entries" ), lineCount );
+    {
+        char * name;
+        char buf[MAX_PATH_LENGTH];
+        tr_strlcpy( buf, b->filename, sizeof( buf ) );
+        name = basename( buf );
+        tr_inf( _( "Blocklist \"%s\" updated with %'d entries" ), name, lineCount );
+    }
+
 
     fclose( out );
     fclose( in );
index 3f7d15340dc728f971dbcbe3024715b78a5e124a..3d5e5b299845aec6eb05a039cd1970dc17be2510 100644 (file)
@@ -17,12 +17,13 @@ struct in_addr;
 typedef struct tr_blocklist tr_blocklist;
 
 tr_blocklist* _tr_blocklistNew         ( const char * filename, int isEnabled );
-void          _tr_blocklistFree        ( tr_blocklist * b );
-int           _tr_blocklistGetRuleCount( tr_blocklist * b );
-int           _tr_blocklistIsEnabled   ( tr_blocklist * b );
-void          _tr_blocklistSetEnabled  ( tr_blocklist * b, int isEnabled );
-int           _tr_blocklistHasAddress  ( tr_blocklist * b, const struct in_addr * addr );
-int           _tr_blocklistExists      ( const tr_blocklist * b );
-int           _tr_blocklistSetContent  ( tr_blocklist * b, const char * filename );
+int           _tr_blocklistExists      ( const tr_blocklist * );
+const char*   _tr_blocklistGetFilename ( const tr_blocklist * );
+int           _tr_blocklistGetRuleCount( const tr_blocklist * );
+void          _tr_blocklistFree        ( tr_blocklist * );
+int           _tr_blocklistIsEnabled   ( tr_blocklist * );
+void          _tr_blocklistSetEnabled  ( tr_blocklist *, int isEnabled );
+int           _tr_blocklistHasAddress  ( tr_blocklist *, const struct in_addr * addr );
+int           _tr_blocklistSetContent  ( tr_blocklist *, const char * filename );
 
 #endif
index 797e9189bc947cd7cfa8cb65c873f57418b65001..e85754267e14c3c1d630149bbab28abe057fa16a 100644 (file)
@@ -1015,7 +1015,7 @@ tr_peerMgrAddIncoming( tr_peerMgr      * manager,
 {
     managerLock( manager );
 
-    if( tr_blocklistHasAddress( manager->handle, addr ) )
+    if( tr_sessionIsAddressBlocked( manager->handle, addr ) )
     {
         tr_dbg( "Banned IP address \"%s\" tried to connect to us",
                 inet_ntoa( *addr ) );
@@ -1053,7 +1053,7 @@ tr_peerMgrAddPex( tr_peerMgr     * manager,
     managerLock( manager );
 
     t = getExistingTorrent( manager, torrentHash );
-    if( !tr_blocklistHasAddress( t->manager->handle, &pex->in_addr ) )
+    if( !tr_sessionIsAddressBlocked( t->manager->handle, &pex->in_addr ) )
         ensureAtomExists( t, &pex->in_addr, pex->port, pex->flags, from );
 
     managerUnlock( manager );
@@ -1799,7 +1799,7 @@ getPeerCandidates( Torrent * t, int * setmeSize )
         }
 
         /* Don't connect to peers in our blocklist */
-        if( tr_blocklistHasAddress( t->manager->handle, &atom->addr ) )
+        if( tr_sessionIsAddressBlocked( t->manager->handle, &atom->addr ) )
             continue;
 
         ret[retCount++] = atom;
index 66a181817ba846b1686ebab28e189f1dbf7c7261..55899f75df5fccaa4c72c3cafa215cb0de12e76b 100644 (file)
@@ -30,7 +30,7 @@ testWildcard( const char * in, const char * expected )
 {
     int ok;
     char * str = cidrize( in );
-fprintf( stderr, "in [%s] out [%s] should be [%s]\n", in, str, expected );
+/* fprintf( stderr, "in [%s] out [%s] should be [%s]\n", in, str, expected ); */
     ok = expected ? !strcmp( expected, str ) : !str;
     tr_free( str );
     return ok;
index 73c4308674e65813fb96e4a1e5fbd9eb209f7f90..02970d167d5dc47b27eafd2a595200b84acd481c 100644 (file)
@@ -116,6 +116,71 @@ tr_sessionSetEncryption( tr_session * session, tr_encryption_mode mode )
 ****
 ***/
 
+static void
+loadBlocklists( tr_session * session )
+{
+    int binCount = 0;
+    int newCount = 0;
+    struct stat sb;
+    char dirname[MAX_PATH_LENGTH];
+    DIR * odir = NULL;
+    tr_list * list = NULL;
+    const int isEnabled = session->isBlocklistEnabled;
+
+    /* walk through the directory and find blocklists */
+    tr_buildPath( dirname, sizeof( dirname ), session->configDir, "blocklists", NULL );
+    if( !stat( dirname, &sb ) && S_ISDIR( sb.st_mode ) && (( odir = opendir( dirname ))))
+    {
+        struct dirent *d;
+        for( d=readdir( odir ); d; d=readdir( odir ) )
+        {
+            char filename[MAX_PATH_LENGTH];
+
+            if( !d->d_name || d->d_name[0]=='.' ) /* skip dotfiles, ., and .. */
+                continue;
+
+            tr_buildPath( filename, sizeof(filename), dirname, d->d_name, NULL );
+
+            if( tr_stringEndsWith( filename, ".bin" ) )
+            {
+                /* if we don't already have this blocklist, add it */
+                if( !tr_list_find( list, filename, (TrListCompareFunc)strcmp ) )
+                {
+                    tr_list_append( &list, _tr_blocklistNew( filename, isEnabled ) );
+                    ++binCount;
+                }
+            }
+            else
+            {
+                /* strip out the file suffix, if there is one, and add ".bin" instead */
+                tr_blocklist * b;
+                const char * dot = strrchr( d->d_name, '.' );
+                const int len = dot ? dot - d->d_name : (int)strlen( d->d_name );
+                char tmp[MAX_PATH_LENGTH];
+                snprintf( tmp, sizeof( tmp ),
+                          "%s%c%*.*s.bin", dirname, TR_PATH_DELIMITER, len, len, d->d_name );
+                b = _tr_blocklistNew( tmp, isEnabled );
+                _tr_blocklistSetContent( b, filename );
+                tr_list_append( &list, b );
+                ++newCount;
+            }
+        }
+
+        closedir( odir );
+    }
+
+    session->blocklists = list;
+
+    if( binCount )
+        tr_dbg( "Found %d blocklists in \"%s\"", binCount, dirname );
+    if( newCount )
+        tr_dbg( "Found %d new blocklists in \"%s\"", newCount, dirname );
+}
+
+/***
+****
+***/
+
 static void metainfoLookupRescan( tr_handle * h );
 
 tr_handle *
@@ -206,8 +271,8 @@ tr_sessionInitFull( const char  * configDir,
     /* initialize the blocklist */
     tr_buildPath( filename, sizeof( filename ), h->configDir, "blocklists", NULL );
     tr_mkdirp( filename, 0777 );
-    tr_buildPath( filename, sizeof( filename ), h->configDir, "blocklists", "level1.bin", NULL );
-    h->blocklist = _tr_blocklistNew( filename, isBlocklistEnabled );
+    h->isBlocklistEnabled = isBlocklistEnabled;
+    loadBlocklists( h );
 
     tr_statsInit( h );
 
@@ -485,8 +550,7 @@ tr_sessionClose( tr_handle * h )
     while( !h->isClosed && !deadlineReached( deadline ) )
         tr_wait( 100 );
 
-    _tr_blocklistFree( h->blocklist );
-    h->blocklist = NULL;
+    tr_list_free( &h->blocklists, (TrListForeachFunc)_tr_blocklistFree );
     tr_webClose( &h->web );
 
     tr_eventClose( h );
@@ -535,11 +599,14 @@ tr_sessionLoadTorrents ( tr_handle   * h,
                 tr_torrent * tor;
                 char filename[MAX_PATH_LENGTH];
                 tr_buildPath( filename, sizeof(filename), dirname, d->d_name, NULL );
-                tr_ctorSetMetainfoFromFile( ctor, filename );
-                tor = tr_torrentNew( h, ctor, NULL );
-                if( tor ) {
-                    tr_list_append( &list, tor );
-                    n++;
+                if( tr_stringEndsWith( filename, ".torrent" ) )
+                {
+                    tr_ctorSetMetainfoFromFile( ctor, filename );
+                    tor = tr_torrentNew( h, ctor, NULL );
+                    if( tor ) {
+                        tr_list_append( &list, tor );
+                        ++n;
+                    }
                 }
             }
         }
@@ -600,39 +667,66 @@ tr_sessionIsPortForwardingEnabled( const tr_handle * h )
 ***/
 
 int
-tr_blocklistGetRuleCount( tr_handle * handle )
+tr_blocklistGetRuleCount( const tr_session * session )
 {
-    return _tr_blocklistGetRuleCount( handle->blocklist );
+    int n = 0;
+    tr_list * l;
+    for( l=session->blocklists; l; l=l->next )
+        n += _tr_blocklistGetRuleCount( l->data );
+    return n;
 }
 
 int
-tr_blocklistIsEnabled( const tr_handle * handle )
+tr_blocklistIsEnabled( const tr_session * session )
 {
-    return _tr_blocklistIsEnabled( handle->blocklist );
+    return session->isBlocklistEnabled;
 }
 
 void
-tr_blocklistSetEnabled( tr_handle * handle, int isEnabled )
+tr_blocklistSetEnabled( tr_session * session, int isEnabled )
 {
-    _tr_blocklistSetEnabled( handle->blocklist, isEnabled );
+    tr_list * l;
+    session->isBlocklistEnabled = isEnabled ? 1 : 0;
+    for( l=session->blocklists; l; l=l->next )
+        _tr_blocklistSetEnabled( l->data, isEnabled );
 }
 
 int
-tr_blocklistExists( const tr_handle * handle )
+tr_blocklistExists( const tr_session * session )
 {
-    return _tr_blocklistExists( handle->blocklist );
+    return session->blocklists != NULL;
 }
 
 int
-tr_blocklistSetContent( tr_handle  * handle, const char * filename )
+tr_blocklistSetContent( tr_session  * session, const char * contentFilename )
 {
-    return _tr_blocklistSetContent( handle->blocklist, filename );
+    tr_list * l;
+    tr_blocklist * b;
+    const char * defaultName = "level1.bin";
+
+    for( b=NULL, l=session->blocklists; !b && l; l=l->next )
+        if( tr_stringEndsWith( _tr_blocklistGetFilename( l->data ), defaultName ) )
+            b = l->data;
+
+    if( !b ) {
+        char filename[MAX_PATH_LENGTH];
+        tr_buildPath( filename, sizeof( filename ), session->configDir, "blocklists", defaultName, NULL );
+        b = _tr_blocklistNew( filename, session->isBlocklistEnabled );
+        tr_list_append( &session->blocklists, b );
+    }
+
+    return _tr_blocklistSetContent( b, contentFilename );
 }
 
 int
-tr_blocklistHasAddress( tr_handle * handle, const struct in_addr * addr )
-{
-    return _tr_blocklistHasAddress( handle->blocklist, addr );
+tr_sessionIsAddressBlocked( const tr_session      * session,
+                            const struct in_addr  * addr )
+{
+    tr_list * l;
+    for( l=session->blocklists; l; l=l->next )
+        if( _tr_blocklistHasAddress( l->data, addr ) )
+            return TRUE;
+    return FALSE;
 }
 
 /***
index 8f5db8b33bf744fdedbad4bf4a49ef87e46e7f68..b54709a80d700c137c3edc0c967444f415dc673d 100644 (file)
@@ -51,6 +51,7 @@ struct tr_handle
 {
     unsigned int                 isPortSet          : 1;
     unsigned int                 isPexEnabled       : 1;
+    unsigned int                 isBlocklistEnabled : 1;
     unsigned int                 isProxyEnabled     : 1;
     unsigned int                 isProxyAuthEnabled : 1;
     unsigned int                 isClosed           : 1;
@@ -80,7 +81,7 @@ struct tr_handle
     struct tr_ratecontrol      * upload;
     struct tr_ratecontrol      * download;
 
-    struct tr_blocklist        * blocklist;
+    struct tr_list             * blocklists;
     struct tr_peerMgr          * peerMgr;
     struct tr_shared           * shared;
 
@@ -106,6 +107,12 @@ void tr_sessionSetTorrentFile( tr_session   * session,
                                const char   * hashString,
                                const char   * filename );
 
+struct in_addr;
+
+int tr_sessionIsAddressBlocked( const tr_session     * session,
+                                const struct in_addr * addr );
+
+
 void tr_globalLock       ( tr_session * );
 void tr_globalUnlock     ( tr_session * );
 int  tr_globalIsLocked   ( const tr_session * );
index 14a9f87c4dc572102b15e5f31a644a29fe0362ef..611602ba9eaa441dae72c0d11d0aefb172f455bd 100644 (file)
@@ -605,22 +605,18 @@ void tr_freeMessageList( tr_msg_list * freeme );
  *
  * Passing NULL for a filename will clear the blocklist.
  */
-int tr_blocklistSetContent( tr_handle  * handle,
-                            const char * filename );
+int tr_blocklistSetContent   ( tr_session       * session,
+                               const char       * filename );
 
-int tr_blocklistGetRuleCount( tr_handle * handle );
+int tr_blocklistGetRuleCount ( const tr_session * session );
 
-int tr_blocklistExists( const tr_handle * handle );
+int tr_blocklistExists       ( const tr_session * session );
 
-int tr_blocklistIsEnabled( const tr_handle * handle );
+int tr_blocklistIsEnabled    ( const tr_session * session );
 
-void tr_blocklistSetEnabled( tr_handle * handle,
-                             int         isEnabled );
+void tr_blocklistSetEnabled  ( tr_session       * session,
+                               int                isEnabled );
 
-struct in_addr;
-
-int tr_blocklistHasAddress( tr_handle             * handle,
-                            const struct in_addr  * addr);
 
 /** @} */
 
index bcdd5d10aaba32d3bd81e465397966569f92de92..2f231f10d10d552248ae1e73316e7bc48554502f 100644 (file)
@@ -93,6 +93,13 @@ main( void )
     tr_free( in );
     tr_free( out );
 
+    /* tr_stringEndsWith */
+    check( tr_stringEndsWith( "the", "the" ) );
+    check( tr_stringEndsWith( "dress", "dress" ) );
+    check( tr_stringEndsWith( "address", "dress" ) );
+    check( !tr_stringEndsWith( "foo.bin", "gfoo.bin" ) );
+    check( !tr_stringEndsWith( "xyz", "xyw" ) );
+
     /* simple bitfield tests */
     for( l=0; l<NUM_LOOPS; ++l )
         if(( i = test_bitfields( )))
index 3afa19c7ef607c571584ecdab20163e14621b37c..fa4c92588b9cd9c348327dd29c1dbd48c6a348bb 100644 (file)
@@ -921,6 +921,14 @@ tr_wait( uint64_t delay_milliseconds )
 ****
 ***/
 
+int
+tr_stringEndsWith( const char * str, const char * end )
+{
+    const size_t slen = strlen( str );
+    const size_t elen = strlen( end );
+    return slen>=elen && !memcmp( &str[slen-elen], end, elen );
+}
+
 /*
  * Copy src to string dst of size siz.  At most siz-1 characters
  * will be copied.  Always NUL terminates (unless siz == 0).
index 5fee7478d43eca26bbf08ec7d9256520a1e2dc34..15a97fec67cece950135e868cbdbe02df6cccbe3 100644 (file)
@@ -197,7 +197,7 @@ char* tr_base64_decode( const void * input, int inlen, int *outlen ) TR_GNUC_MAL
 
 size_t tr_strlcpy( char * dst, const char * src, size_t siz );
 
-
+int   tr_stringEndsWith( const char * string, const char * end );
 
 const char* tr_strerror( int );