[Debtorrent-commits] r85 - in /debtorrent/branches/http-listen/DebTorrent: BT1/AptListener.py download_bt1.py

camrdale-guest at users.alioth.debian.org camrdale-guest at users.alioth.debian.org
Mon Jun 4 05:05:11 UTC 2007


Author: camrdale-guest
Date: Mon Jun  4 05:05:08 2007
New Revision: 85

URL: http://svn.debian.org/wsvn/debtorrent/?sc=1&rev=85
Log:
Make AptListener proxy download all requested files.
Add AptListener configuration options.

Modified:
    debtorrent/branches/http-listen/DebTorrent/BT1/AptListener.py
    debtorrent/branches/http-listen/DebTorrent/download_bt1.py

Modified: debtorrent/branches/http-listen/DebTorrent/BT1/AptListener.py
URL: http://svn.debian.org/wsvn/debtorrent/debtorrent/branches/http-listen/DebTorrent/BT1/AptListener.py?rev=85&op=diff
==============================================================================
--- debtorrent/branches/http-listen/DebTorrent/BT1/AptListener.py (original)
+++ debtorrent/branches/http-listen/DebTorrent/BT1/AptListener.py Mon Jun  4 05:05:08 2007
@@ -44,6 +44,8 @@
     True = 1
     False = 0
     bool = lambda x: not not x
+    
+DEBUG = True
 
 def statefiletemplate(x):
     """Check the saved state file for corruption.
@@ -190,10 +192,9 @@
         """
         
         self.config = config
-        return
         self.dfile = config['dfile']
         favicon = config['favicon']
-        self.parse_dir_interval = config['parse_dir_interval']
+        self.parse_dir_interval = config['apt_parse_dir_interval']
         self.favicon = None
         if favicon:
             try:
@@ -231,7 +232,7 @@
                 
         self.save_dfile_interval = config['save_dfile_interval']
         self.show_names = config['show_names']
-        rawserver.add_task(self.save_state, self.save_dfile_interval)
+        #rawserver.add_task(self.save_state, self.save_dfile_interval)
         self.prevtime = clock()
         self.logfile = None
         self.log = None
@@ -267,7 +268,6 @@
             self.allowed_list_mtime = 0
             self.parse_allowed()
             self.remove_from_state('allowed','allowed_dir_files')
-            config['allowed_controls'] = 0
 
         elif config['allowed_dir']:
             self.allowed = self.state.setdefault('allowed',{})
@@ -279,7 +279,6 @@
         else:
             self.allowed = None
             self.remove_from_state('allowed','allowed_dir_files', 'allowed_list')
-            config['allowed_controls'] = 0
                 
         self.uq_broken = unquote('+') != ' '
         self.Filter = Filter(rawserver.add_task)
@@ -287,7 +286,7 @@
     def get_infopage(self):
         """Format the info page to display for normal browsers.
         
-        Formats the currently tracked torrents into a table in human-readable
+        Formats the currently downloading torrents into a table in human-readable
         format to display in a browser window.
         
         @rtype: (C{int}, C{string}, C{dictionary}, C{string})
@@ -311,8 +310,8 @@
             s.write('</head>\n<body>\n' \
                 '<h3>DebTorrent download info</h3>\n'\
                 '<ul>\n'
-                '<li><strong>tracker version:</strong> %s</li>\n' \
-                '<li><strong>server time:</strong> %s</li>\n' \
+                '<li><strong>client version:</strong> %s</li>\n' \
+                '<li><strong>client time:</strong> %s</li>\n' \
                 '</ul>\n' % (version, isotime()))
             if self.config['allowed_dir']:
                 if self.show_names:
@@ -324,7 +323,7 @@
             else:
                 names = [ (None,hash) for hash in self.downloads.keys() ]
             if not names:
-                s.write('<p>not tracking any files yet...</p>\n')
+                s.write('<p>not downloading any files yet...</p>\n')
             else:
                 names.sort()
                 tn = 0
@@ -386,72 +385,39 @@
             return (500, 'Internal Server Error', {'Content-Type': 'text/html; charset=iso-8859-1'}, 'Server Error')
 
 
-    def get_file(self, hash):
-        """Get the metainfo file for a torrent.
-        
-        @type hash: C{string}
-        @param hash: the infohash of the torrent to get the metainfo of
+    def get_file(self, path):
+        """Proxy the download of a file from a mirror.
+        
+        @type path: C{list} of C{string}
+        @param hash: the path of the file to download, starting with the mirror name
         @rtype: (C{int}, C{string}, C{dictionary}, C{string})
         @return: the HTTP status code, status message, headers, and bencoded 
             metainfo file
         
         """
         
-        if not self.allow_get:
-            return (400, 'Not Authorized', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'},
-                'get function is not available with this tracker.')
-        if not self.allowed.has_key(hash):
-            return (404, 'Not Found', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'}, alas)
-        fname = self.allowed[hash]['file']
-        fpath = self.allowed[hash]['path']
-        return (200, 'OK', {'Content-Type': 'application/x-debtorrent',
-            'Content-Disposition': 'attachment; filename=' + fname},
-            open(fpath, 'rb').read())
-
-
-    def check_allowed(self, infohash, paramslist):
-        """Determine whether the tracker is tracking this torrent.
-        
-        @type infohash: C{string}
-        @param infohash: the infohash of the torrent to check
-        @type paramslist: C{dictionary}
-        @param paramslist: the query parameters from the GET request
-        @rtype: (C{int}, C{string}, C{dictionary}, C{string})
-        @return: the HTTP status code, status message, headers, and bencoded 
-            message body if the request is not allowed, or None if it is
-
-        """
-        
-        if ( self.aggregator_key is not None
-                and not ( paramslist.has_key('password')
-                        and paramslist['password'][0] == self.aggregator_key ) ):
-            return (200, 'Not Authorized', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'},
-                bencode({'failure reason':
-                'Requested download is not authorized for use with this tracker.'}))
-
-        if self.allowed is not None:
-            if not self.allowed.has_key(infohash):
-                return (200, 'Not Authorized', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'},
-                    bencode({'failure reason':
-                    'Requested download is not authorized for use with this tracker.'}))
-            if self.config['allowed_controls']:
-                if self.allowed[infohash].has_key('failure reason'):
-                    return (200, 'Not Authorized', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'},
-                        bencode({'failure reason': self.allowed[infohash]['failure reason']}))
-
-        if paramslist.has_key('tracker'):
-            if ( self.config['multitracker_allowed'] == 'none' or       # turned off
-                          paramslist['peer_id'][0] == self.trackerid ): # oops! contacted myself
-                return (200, 'Not Authorized', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'},
-                    bencode({'failure reason': 'disallowed'}))
-            
-            if ( self.config['multitracker_allowed'] == 'autodetect'
-                        and not self.allowed[infohash].has_key('announce-list') ):
-                return (200, 'Not Authorized', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'},
-                    bencode({'failure reason':
-                    'Requested download is not authorized for multitracker use.'}))
-
-        return None
+        try:
+            url = 'http://'
+            url += '/'.join(path)
+            if DEBUG:
+                print 'fetching:', url
+            f = urlopen(url)
+            headers = {}
+            for k,v in f.response.getheaders():
+                if k.lower() != 'content-length':
+                    headers[k] = v
+            data = f.read()
+            
+            return (200, 'OK', headers, data)
+        
+        except IOError, e:
+            try:
+                (msg, status) = e
+            except:
+                status = 404
+                msg = 'Unknown error occurred'
+            return (status, 'Not Found', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'}, msg)
+            
 
 
     def get(self, connection, path, headers):
@@ -488,16 +454,7 @@
              or (self.banned_IPs and self.banned_IPs.includes(ip)) ):
             return (400, 'Not Authorized', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'},
                 bencode({'failure reason':
-                'your IP is not allowed on this tracker'}))
-
-        nip = get_forwarded_ip(headers)
-        if nip and not self.only_local_override_ip:
-            ip = nip
-            try:
-                ip = to_ipv4(ip)
-                ipv4 = True
-            except ValueError:
-                ipv4 = False
+                'your IP is not allowed on this proxy'}))
 
         paramslist = {}
         def params(key, default = None, l = paramslist):
@@ -534,78 +491,29 @@
                     
             if path == '' or path == 'index.html':
                 return self.get_infopage()
-            if (path == 'file'):
-                return self.get_file(params('info_hash'))
-            if path == 'favicon.ico' and self.favicon is not None:
-                return (200, 'OK', {'Content-Type' : 'image/x-icon'}, self.favicon)
-
-            # automated access from here on
-
-            if path in ('scrape', 'scrape.php', 'tracker.php/scrape'):
-                return self.get_scrape(paramslist)
-            
-            if not path in ('announce', 'announce.php', 'tracker.php/announce'):
+            if path == 'favicon.ico':
+                if self.favicon is not None:
+                    return (200, 'OK', {'Content-Type' : 'image/x-icon'}, self.favicon)
+                else:
+                    return (404, 'Not Found', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'}, alas)
+
+            # Process the rest as a proxy
+            path = path.split('/')
+
+            if 'Packages.diff' in path:
                 return (404, 'Not Found', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'}, alas)
 
-            # main tracker function
-
-            filtered = self.Filter.check(real_ip, paramslist, headers)
-            if filtered:
-                return (400, 'Not Authorized', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'},
-                    bencode({'failure reason': filtered}))
-            
-            infohash = params('info_hash')
-            if not infohash:
-                raise ValueError, 'no info hash'
-
-            notallowed = self.check_allowed(infohash, paramslist)
-            if notallowed:
-                return notallowed
-
-            event = params('event')
-
-            rsize = self.add_data(infohash, event, ip, paramslist)
-
+#            if path[-1] in ('Packages', 'Packages.gz', 'Packages.bz2'):
+#                return self.get_Packages(path)
+
+#            if path[-1][-4:] == '.deb':
+#                return self.get_package(path)
+            
+            return self.get_file(path)
+            
         except ValueError, e:
             return (400, 'Bad Request', {'Content-Type': 'text/plain'}, 
                 'you sent me garbage - ' + str(e))
-
-        if self.aggregate_forward and not paramslist.has_key('tracker'):
-            self.aggregate_senddata(query)
-
-        if self.is_aggregator:      # don't return peer data here
-            return (200, 'OK', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'},
-                    bencode({'response': 'OK'}))
-
-        if params('compact') and ipv4:
-            if params('requirecrypto'):
-                return_type = 1
-            elif params('supportcrypto'):
-                return_type = 2
-            else:
-                return_type = 0
-        elif self.config['compact_reqd'] and ipv4:
-            return (400, 'Bad Request', {'Content-Type': 'text/plain'}, 
-                'your client is outdated, please upgrade')
-        elif params('no_peer_id'):
-            return_type = 4
-        else:
-            return_type = 3
-            
-        data = self.peerlist(infohash, event=='stopped',
-                             params('tracker'), not params('left'),
-                             return_type, rsize, params('supportcrypto'))
-
-        if paramslist.has_key('scrape'):    # deprecated
-            data['scrape'] = self.scrapedata(infohash, False)
-
-        if self.dedicated_seed_id:
-            if params('seed_id') == self.dedicated_seed_id and params('left') == 0:
-                self.is_seeded[infohash] = True
-            if params('check_seeded') and self.is_seeded.get(infohash):
-                data['seeded'] = 1
-            
-        return (200, 'OK', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'}, bencode(data))
 
 
     def remove_from_state(self, *l):

Modified: debtorrent/branches/http-listen/DebTorrent/download_bt1.py
URL: http://svn.debian.org/wsvn/debtorrent/debtorrent/branches/http-listen/DebTorrent/download_bt1.py?rev=85&op=diff
==============================================================================
--- debtorrent/branches/http-listen/DebTorrent/download_bt1.py (original)
+++ debtorrent/branches/http-listen/DebTorrent/download_bt1.py Mon Jun  4 05:05:08 2007
@@ -194,6 +194,30 @@
         "minutes between automatic flushes to disk (0 = disabled)"),
     ('dedicated_seed_id', '',
         "code to send to tracker identifying as a dedicated seed"),
+    ('dfile', '', 'file to store recent apt downloader info in'),
+    ('socket_timeout', 15, 'timeout for closing connections'),
+    ('save_dfile_interval', 5 * 60, 'seconds between saving dfile'),
+    ('min_time_between_log_flushes', 3.0,
+        'minimum time it must have been since the last flush to do another one'),
+    ('min_time_between_cache_refreshes', 600.0,
+        'minimum time in seconds before a cache is considered stale and is flushed'),
+    ('allowed_dir', '', 'only allow downloads for .dtorrents in this dir'),
+    ('allowed_list', '', 'only allow downloads for hashes in this list (hex format, one per line)'),
+    ('hupmonitor', 0, 'whether to reopen the log file upon receipt of HUP signal'),
+    ('http_timeout', 60, 
+        'number of seconds to wait before assuming that an http connection has timed out'),
+    ('apt_parse_dir_interval', 60, 'seconds between reloading of allowed_dir or allowed_file ' +
+             'and allowed_ips and banned_ips lists for apt'),
+    ('show_infopage', 1, "whether to display an info page when the tracker's root dir is loaded"),
+    ('infopage_redirect', '', 'a URL to redirect the info page to'),
+    ('show_names', 1, 'whether to display names from allowed dir'),
+    ('favicon', '', 'file containing x-icon data to return when browser requests favicon.ico'),
+    ('allowed_ips', '', 'only allow connections from IPs specified in the given file; '+
+             'file contains subnet data in the format: aa.bb.cc.dd/len'),
+    ('banned_ips', '', "don't allow connections from IPs specified in the given file; "+
+             'file contains IP range data in the format: xxx:xxx:ip1-ip2'),
+    ('logfile', '', 'file to write the tracker logs, use - for stdout (default)'),
+    ('allow_get', 0, 'use with allowed_dir; adds a /file?hash={hash} url that allows users to download the torrent file'),
     ]
 
 argslistheader = 'Arguments are:\n\n'




More information about the Debtorrent-commits mailing list