r187 - in /debtorrent/trunk/DebTorrent/BT1: FileSelector.py NatCheck.py

camrdale-guest at users.alioth.debian.org camrdale-guest at users.alioth.debian.org
Sat Jul 28 02:58:34 UTC 2007


Author: camrdale-guest
Date: Sat Jul 28 02:58:33 2007
New Revision: 187

URL: http://svn.debian.org/wsvn/debtorrent/?sc=1&rev=187
Log:
More documentation.

Modified:
    debtorrent/trunk/DebTorrent/BT1/FileSelector.py
    debtorrent/trunk/DebTorrent/BT1/NatCheck.py

Modified: debtorrent/trunk/DebTorrent/BT1/FileSelector.py
URL: http://svn.debian.org/wsvn/debtorrent/debtorrent/trunk/DebTorrent/BT1/FileSelector.py?rev=187&op=diff
==============================================================================
--- debtorrent/trunk/DebTorrent/BT1/FileSelector.py (original)
+++ debtorrent/trunk/DebTorrent/BT1/FileSelector.py Sat Jul 28 02:58:33 2007
@@ -18,42 +18,48 @@
 class FileSelector:
     """Enable the selective downloading of files within a torrent.
     
-    @type files: unknown
-    @ivar files: unknown
-    @type storage: unknown
-    @ivar storage: unknown
-    @type storagewrapper: unknown
-    @ivar storagewrapper: unknown
-    @type sched: unknown
-    @ivar sched: unknown
-    @type failfunc: unknown
-    @ivar failfunc: unknown
+    @type files: C{list} of (C{list} of C{string}, C{long})
+    @ivar files: the paths and sizes of the files
+    @type storage: L{Storage.Storage}
+    @ivar storage: the Storage instance to use
+    @type storagewrapper: L{StorageWrapper.StorageWrapper}
+    @ivar storagewrapper: the StorageWrapper instance to use
+    @type sched: C{method}
+    @ivar sched: the mehtod to call to schedule a future invocation of a function
+    @type failfunc: C{method}
+    @ivar failfunc: the method to call to indicate an error has occurred
     @type downloader: unknown
-    @ivar downloader: unknown
-    @type picker: unknown
-    @ivar picker: unknown
-    @type numfiles: unknown
-    @ivar numfiles: unknown
-    @type priority: unknown
-    @ivar priority: unknown
-    @type new_priority: unknown
-    @ivar new_priority: unknown
-    @type new_partials: unknown
-    @ivar new_partials: unknown
-    @type filepieces: unknown
-    @ivar filepieces: unknown
-    @type numpieces: unknown
-    @ivar numpieces: unknown
-    @type piece_priority: unknown
-    @ivar piece_priority: unknown
-    @type cancelfunc: unknown
-    @ivar cancelfunc: unknown
-    @type requestmorefunc: unknown
-    @ivar requestmorefunc: unknown
-    @type rerequestfunc: unknown
-    @ivar rerequestfunc: unknown
-    @type new_piece_priority: unknown
-    @ivar new_piece_priority: unknown
+    @ivar downloader: not used
+    @type picker: L{PiecePicker.PiecePicker}
+    @ivar picker: the PiecePicker instance to use
+    @type numfiles: C{int}
+    @ivar numfiles: the number of files in the download
+    @type priority: C{list} of C{int}
+    @ivar priority: the current priority of each file in the download::
+        -1 -- do not download
+         0 -- highest priority
+         1 -- medium priority
+         2 -- lowest priority
+    @type new_priority: C{list} of C{int}
+    @ivar new_priority: the new priority of each file in the download
+    @type new_partials: C{list} of C{int}
+    @ivar new_partials: the new list of partially completed pieces to process
+    @type filepieces: C{list} of C{tuple}
+    @ivar filepieces: an ordered list, one for each file, containing a tuple of
+        the pieces that belong to that file
+    @type numpieces: C{int}
+    @ivar numpieces: the number of pieces in the download
+    @type piece_priority: C{list} of C{int}
+    @ivar piece_priority: the current priority for each piece in the download
+    @type cancelfunc: C{method}
+    @ivar cancelfunc: method to call to cancel piece downloads
+    @type requestmorefunc: C{method}
+    @ivar requestmorefunc: method to call to request more peers for a
+        newly enabled piece download
+    @type rerequestfunc: C{method}
+    @ivar rerequestfunc: method to call to request more peers
+    @type new_piece_priority: C{list} of C{int}
+    @ivar new_piece_priority: the new priority for each piece in the download
     
     """
     
@@ -61,22 +67,22 @@
                  storage, storagewrapper, sched, picker, failfunc):
         """Initialize the instance.
         
-        @type files: unknown
-        @param files: unknown
-        @type piece_lengths: unknown
-        @param piece_lengths: unknown
-        @type bufferdir: unknown
-        @param bufferdir: unknown
-        @type storage: unknown
-        @param storage: unknown
-        @type storagewrapper: unknown
-        @param storagewrapper: unknown
-        @type sched: unknown
-        @param sched: unknown
-        @type picker: unknown
-        @param picker: unknown
-        @type failfunc: unknown
-        @param failfunc: unknown
+        @type files: C{list} of (C{list} of C{string}, C{long})
+        @param files: the paths and sizes of the files
+        @type piece_lengths: C{list} of C{int}
+        @param piece_lengths: the sizes of the pieces
+        @type bufferdir: C{string}
+        @param bufferdir: the directory to store the buffered pieces in
+        @type storage: L{Storage.Storage}
+        @param storage: the Storage instance to use
+        @type storagewrapper: L{StorageWrapper.StorageWrapper}
+        @param storagewrapper: the StorageWrapper instance to use
+        @type sched: C{method}
+        @param sched: the mehtod to call to schedule a future invocation of a function
+        @type picker: L{PiecePicker.PiecePicker}
+        @param picker: the PiecePicker instance to use
+        @type failfunc: C{method}
+        @param failfunc: the method to call to indicate an error has occurred
         
         """
         
@@ -120,10 +126,12 @@
 
 
     def init_priority(self, new_priority):
-        """
-        
-        @type new_priority: unknown
-        @param new_priority: unknown
+        """Initialize the priorities of all the files.
+        
+        @type new_priority: C{list} of C{int}
+        @param new_priority: the new file priorities
+        @rtype: C{boolean}
+        @return: whether the initialization was successful
         
         """
         
@@ -150,14 +158,25 @@
             return False
         return True
 
-    '''
-    d['priority'] = [file #1 priority [,file #2 priority...] ]
-                    a list of download priorities for each file.
-                    Priority may be -1, 0, 1, 2.  -1 = download disabled,
-                    0 = highest, 1 = normal, 2 = lowest.
-    Also see Storage.pickle and StorageWrapper.pickle for additional keys.
-    '''
     def unpickle(self, d):
+        """Unpickle the previously saved state.
+        
+        Data is in the format:
+            d['priority'] = [file #1 priority, file #2 priority, ...]
+        
+        It is a list of download priorities for each file. The priority may be::
+            -1 -- download disabled
+             0 -- highest
+             1 -- normal
+             2 -- lowest
+
+        Also see Storage.pickle and StorageWrapper.pickle for additional keys.
+
+        @type d: C{dictionary}
+        @param d: the pickled state data
+        
+        """
+        
         if d.has_key('priority'):
             if not self.init_priority(d['priority']):
                 return
@@ -171,6 +190,18 @@
 
 
     def tie_in(self, cancelfunc, requestmorefunc, rerequestfunc):
+        """Set some instance variables that weren't available at initialization.
+        
+        @type cancelfunc: C{method}
+        @param cancelfunc: method to call to cancel piece downloads
+        @type requestmorefunc: C{method}
+        @param requestmorefunc: method to call to request more peers for a
+            newly enabled piece download
+        @type rerequestfunc: C{method}
+        @param rerequestfunc: method to call to request more peers
+        
+        """
+        
         self.cancelfunc = cancelfunc
         self.requestmorefunc = requestmorefunc
         self.rerequestfunc = rerequestfunc
@@ -188,6 +219,17 @@
         
 
     def _initialize_files_disabled(self, old_priority, new_priority):
+        """Initialize the disabled files on startup.
+        
+        @type old_priority: C{list} of C{int}
+        @param old_priority: the old file priorities
+        @type new_priority: C{list} of C{int}
+        @param new_priority: the new file priorities
+        @rtype: C{boolean}
+        @return: whether the initialization was successful
+        
+        """
+        
         old_disabled = [p == -1 for p in old_priority]
         new_disabled = [p == -1 for p in new_priority]
         files_updated = False        
@@ -212,6 +254,17 @@
 
 
     def _set_files_disabled(self, old_priority, new_priority):
+        """Disable files based on a new priority setting.
+        
+        @type old_priority: C{list} of C{int}
+        @param old_priority: the old file priorities
+        @type new_priority: C{list} of C{int}
+        @param new_priority: the new file priorities
+        @rtype: C{boolean}
+        @return: whether the disabling was successful
+        
+        """
+        
         old_disabled = [p == -1 for p in old_priority]
         new_disabled = [p == -1 for p in new_priority]
         data_to_update = []
@@ -258,6 +311,14 @@
 
 
     def _get_piece_priority_list(self, file_priority_list):
+        """Create a piece priority list from a file priority list.
+        
+        @type file_priority_list: C{list} of C{int}
+        @param file_priority_list: the file priorities
+        @rtype: C{list} of C{int}
+        @return: the new piece priorities
+        
+        """
         l = [-1] * self.numpieces
         for f in xrange(self.numfiles):
             if file_priority_list[f] == -1:
@@ -271,6 +332,15 @@
         
 
     def _initialize_piece_priority(self, new_priority):
+        """Initialize the piece priorities on startup.
+        
+        @type new_priority: C{list} of C{int}
+        @param new_priority: the new file priorities
+        @rtype: C{list} of C{int}
+        @return: the new piece priorities
+        
+        """
+        
         new_piece_priority = self._get_piece_priority_list(new_priority)
         pieces = range(self.numpieces)
         shuffle(pieces)
@@ -282,6 +352,15 @@
 
 
     def _set_piece_priority(self, new_priority):
+        """Disable pieces base on a new file priority setting.
+        
+        @type new_priority: C{list} of C{int}
+        @param new_priority: the new file priorities
+        @rtype: C{list} of C{int}
+        @return: the new piece priorities
+        
+        """
+        
         was_complete = self.storagewrapper.am_I_complete()
         new_piece_priority = self._get_piece_priority_list(new_priority)
         pieces = range(self.numpieces)
@@ -308,6 +387,14 @@
 
 
     def initialize_priorities_now(self, new_priority = None):
+        """Initialize the priorities on startup.
+        
+        @type new_priority: C{list} of C{int}
+        @param new_priority: the new file priorities
+            (optional, defaults to not initializing anything)
+        
+        """
+
         if not new_priority:
             return
         old_priority = self.priority
@@ -317,6 +404,14 @@
         self.piece_priority = self._initialize_piece_priority(new_priority)
 
     def set_priorities_now(self, new_priority = None):
+        """Set the new priorities.
+        
+        @type new_priority: C{list} of C{int}
+        @param new_priority: the new file priorities
+            (optional, defaults to using the saved L{new_priority})
+        
+        """
+
         if not new_priority:
             new_priority = self.new_priority
             self.new_priority = None    # potential race condition
@@ -329,24 +424,65 @@
         self.piece_priority = self._set_piece_priority(new_priority)
 
     def set_priorities(self, new_priority):
+        """Schedule the future setting of the new priorities.
+        
+        @type new_priority: C{list} of C{int}
+        @param new_priority: the new file priorities
+        
+        """
+
         self.new_priority = new_priority
         self.sched(self.set_priorities_now)
         
     def set_priority(self, f, p):
+        """Set the priority of a single file.
+        
+        @type f: C{int}
+        @param f: the index of the file to set the priority of
+        @type p: C{int}
+        @param p: the new priority for the file
+        
+        """
+        
         new_priority = self.get_priorities()
         new_priority[f] = p
         self.set_priorities(new_priority)
 
     def get_priorities(self):
+        """Get the current (or soon to be set) file priorities.
+        
+        @rtype: C{list} of C{int}
+        @return: the current file priorities
+        
+        """
+        
         priority = self.new_priority
         if not priority:
             priority = self.priority    # potential race condition
         return [i for i in priority]
 
     def __setitem__(self, index, val):
+        """Set the priority for the file.
+        
+        @type index: C{int}
+        @param index: the index of the file to set the priority of
+        @type val: C{int}
+        @param val: the new priority for the file
+        
+        """
+        
         self.set_priority(index, val)
 
     def __getitem__(self, index):
+        """Get the priority for the file.
+        
+        @type index: C{int}
+        @param index: the index of the file to get the priority of
+        @rtype: C{int}
+        @return: the priority for the file
+
+        """
+        
         try:
             return self.new_priority[index]
         except:
@@ -354,11 +490,20 @@
 
 
     def finish(self):
+        """Delete disabled files when the download is being shutdown."""
         for f in xrange(self.numfiles):
             if self.priority[f] == -1:
                 self.storage.delete_file(f)
 
     def pickle(self):
+        """Pickle the current state for later.
+        
+        @see: L{unpickle}
+        @rtype: C{dictionary}
+        @return: the pickled data
+        
+        """
+        
         d = {'priority': self.priority}
         try:
             s = self.storage.pickle()

Modified: debtorrent/trunk/DebTorrent/BT1/NatCheck.py
URL: http://svn.debian.org/wsvn/debtorrent/debtorrent/trunk/DebTorrent/BT1/NatCheck.py?rev=187&op=diff
==============================================================================
--- debtorrent/trunk/DebTorrent/BT1/NatCheck.py (original)
+++ debtorrent/trunk/DebTorrent/BT1/NatCheck.py Sat Jul 28 02:58:33 2007
@@ -1,8 +1,15 @@
 # Written by Bram Cohen
 # Modified by Cameron Dale
 # see LICENSE.txt for license information
-
+#
 # $Id$
+
+"""Check if a peer is unreachable behind a NAT.
+
+ at type CHECK_PEER_ID_ENCRYPTED: C{boolean}
+ at var CHECK_PEER_ID_ENCRYPTED: whether to check if connecting peers are encrypted
+
+"""
 
 from cStringIO import StringIO
 from socket import error as socketerror
@@ -20,8 +27,68 @@
 # header, reserved, download id, my id, [length, message]
 
 class NatCheck:
+    """Check if a peer is unreachable behind a NAT.
+    
+    @type resultfunc: C{method}
+    @ivar resultfunc: the method to call with the result when complete
+    @type downloadid: C{string}
+    @ivar downloadid: the info hash of the torrent to use
+    @type peerid: C{string}
+    @ivar peerid: the peer ID of the peer being checked
+    @type ip: C{string}
+    @ivar ip: the IP of the peer being checked
+    @type port: C{int}
+    @ivar port: the port to connect to the peer on
+    @type encrypted: C{boolean}
+    @ivar encrypted: whether to use an encrypted connection
+    @type closed: C{boolean}
+    @ivar closed: whether the connection has been closed
+    @type buffer: C{string}
+    @ivar buffer: the buffer of received data from the connection
+    @type read: C{method}
+    @ivar read: the method to use to read from the connection
+    @type write: C{method}
+    @ivar write: the method to use to write to the connection
+    @type connection: L{DebTorrent.SocketHandler.SingleSocket}
+    @ivar connection: the connection to the peer
+    @type _dc: C{boolean}
+    @ivar _dc: whether encrypted connections have been disabled
+    @type encrypter: L{DebTorrent.BTcrypto.Crypto}
+    @ivar encrypter: the encrypter to use for the connection
+    @type next_len: C{int}
+    @ivar next_len: the next amount of data to read from the connection
+    @type next_func: C{method}
+    @ivar next_func: the next method to use to process incoming data on the 
+        connection
+    @type _max_search: C{int}
+    @ivar _max_search: the number of remaining bytes to search for the pattern
+    @type cryptmode: C{int}
+    @ivar cryptmode: the type of encryption being used
+    
+    """
+    
     def __init__(self, resultfunc, downloadid, peerid, ip, port, rawserver,
                  encrypted = False):
+        """Initialize the instance and start a connection to the peer.
+        
+        @type resultfunc: C{method}
+        @param resultfunc: the method to call with the result when complete
+        @type downloadid: C{string}
+        @param downloadid: the info hash of the torrent to use
+        @type peerid: C{string}
+        @param peerid: the peer ID of the peer being checked
+        @type ip: C{string}
+        @param ip: the IP of the peer being checked
+        @type port: C{int}
+        @param port: the port to connect to the peer on
+        @type rawserver: L{DebTorrent.RawServer.RawServer}
+        @param rawserver: the server instance to use
+        @type encrypted: C{boolean}
+        @param encrypted: whether to use an encrypted connection
+            (optional, defaults to False)
+        
+        """
+        
         self.resultfunc = resultfunc
         self.downloadid = downloadid
         self.peerid = peerid
@@ -49,6 +116,13 @@
         self.next_len, self.next_func = 1+len(protocol_name), self.read_header
 
     def answer(self, result):
+        """Close the connection and return the result.
+        
+        @type result: C{boolean}
+        @param result: whether the peer is connectable
+        
+        """
+        
         self.closed = True
         try:
             self.connection.close()
@@ -57,11 +131,31 @@
         self.resultfunc(result, self.downloadid, self.peerid, self.ip, self.port)
 
     def _read_header(self, s):
+        """Read the protocol header.
+        
+        @type s: C{string}
+        @param s: the incoming data from the connection
+        @rtype: C{int}, C{method}
+        @return: the next amount of data to read and the method to call with
+            it, or None if there is no next method to call
+        
+        """
+        
         if s == chr(len(protocol_name))+protocol_name:
             return 8, self.read_options
         return None
 
     def read_header(self, s):
+        """Read the possibly encrypted protocol header.
+        
+        @type s: C{string}
+        @param s: the incoming data from the connection
+        @rtype: C{int}, C{method}
+        @return: the next amount of data to read and the method to call with
+            it, or None if there is no next method to call
+        
+        """
+        
         if self._read_header(s):
             if self.encrypted:
                 return None
@@ -74,6 +168,7 @@
     ################## ENCRYPTION SUPPORT ######################
 
     def _start_crypto(self):
+        """Setup the instance for the encrypted connection."""
         self.encrypter.setrawaccess(self._read,self._write)
         self.write = self.encrypter.write
         self.read = self.encrypter.read
@@ -81,6 +176,16 @@
             self.buffer = self.encrypter.decrypt(self.buffer)
 
     def read_crypto_header(self, s):
+        """Read the encryption key.
+        
+        @type s: C{string}
+        @param s: the incoming data from the connection
+        @rtype: C{int}, C{method}
+        @return: the next amount of data to read and the method to call with
+            it, or None if there is no next method to call
+        
+        """
+        
         self.encrypter.received_key(s)
         self.encrypter.set_skey(self.downloadid)
         cryptmode = '\x00\x00\x00\x02'    # full stream encryption
@@ -97,6 +202,17 @@
         return 1, self.read_crypto_block4a
 
     def _search_for_pattern(self, s, pat):
+        """Search for a patter in the encrypted protocol header.
+        
+        @type s: C{string}
+        @param s: the incoming data from the connection
+        @type pat: C{string}
+        @param pat: the pattern to find
+        @rtype: C{boolean}
+        @return: whether the pattern was found
+        
+        """
+        
         p = s.find(pat)
         if p < 0:
             if len(s) >= len(pat):
@@ -112,6 +228,16 @@
     ### OUTGOING CONNECTION ###
 
     def read_crypto_block4a(self, s):
+        """Read the encrypted protocol header.
+        
+        @type s: C{string}
+        @param s: the incoming data from the connection
+        @rtype: C{int}, C{method}
+        @return: the next amount of data to read and the method to call with
+            it, or None if there is no next method to call
+        
+        """
+        
         if not self._search_for_pattern(s,self.encrypter.VC_pattern()):
             return -1, self.read_crypto_block4a     # wait for more data
         if self._dc:                        # can't or won't go any further
@@ -121,6 +247,16 @@
         return 6, self.read_crypto_block4b
 
     def read_crypto_block4b(self, s):
+        """Read the encrypted protocol mode and padding.
+        
+        @type s: C{string}
+        @param s: the incoming data from the connection
+        @rtype: C{int}, C{method}
+        @return: the next amount of data to read and the method to call with
+            it, or None if there is no next method to call
+        
+        """
+        
         self.cryptmode = toint(s[:4]) % 4
         if self.cryptmode != 2:
             return None                     # unknown encryption
@@ -132,10 +268,28 @@
         return self.read_crypto_block4done()
 
     def read_crypto_pad4(self, s):
+        """Read the encrypted protocol padding.
+        
+        @type s: C{string}
+        @param s: the incoming data from the connection
+        @rtype: C{int}, C{method}
+        @return: the next amount of data to read and the method to call with
+            it, or None if there is no next method to call
+        
+        """
+        
         # discard data
         return self.read_crypto_block4done()
 
     def read_crypto_block4done(self):
+        """Finish with the encrypted header.
+        
+        @rtype: C{int}, C{method}
+        @return: the next amount of data to read and the method to call with
+            it, or None if there is no next method to call
+        
+        """
+        
         if self.cryptmode == 1:     # only handshake encryption
             if not self.buffer:  # oops; check for exceptions to this
                 return None
@@ -147,35 +301,104 @@
     ### START PROTOCOL OVER ENCRYPTED CONNECTION ###
 
     def read_encrypted_header(self, s):
+        """Read the regular protocol name header from the encrypted stream.
+        
+        @type s: C{string}
+        @param s: the incoming data from the connection
+        @rtype: C{int}, C{method}
+        @return: the next amount of data to read and the method to call with
+            it, or None if there is no next method to call
+        
+        """
+        
         return self._read_header(s)
 
     ################################################
 
     def read_options(self, s):
+        """Read the options from the header.
+        
+        @type s: C{string}
+        @param s: the incoming data from the connection
+        @rtype: C{int}, C{method}
+        @return: the next amount of data to read and the method to call with
+            it, or None if there is no next method to call
+        
+        """
+        
         return 20, self.read_download_id
 
     def read_download_id(self, s):
+        """Verify the torrent infohash from the header.
+        
+        @type s: C{string}
+        @param s: the incoming data from the connection
+        @rtype: C{int}, C{method}
+        @return: the next amount of data to read and the method to call with
+            it, or None if there is no next method to call
+        
+        """
+        
         if s != self.downloadid:
             return None
         return 20, self.read_peer_id
 
     def read_peer_id(self, s):
+        """Verify the peer's ID and return the answer.
+        
+        @type s: C{string}
+        @param s: the incoming data from the connection
+        @rtype: None
+        @return: None
+        
+        """
+        
         if s != self.peerid:
             return None
         self.answer(True)
         return None
 
     def _write(self, message):
+        """Write a raw message out on the connection.
+        
+        @type message: C{string}
+        @param message: the raw data to write to the connection
+        
+        """
+        
         if not self.closed:
             self.connection.write(message)
 
     def data_came_in(self, connection, s):
+        """Process the incoming data on the connection.
+        
+        @type connection: L{DebTorrent.SocketHandler.SingleSocket}
+        @param connection: the connection the data came in on (not used)
+        @type s: C{string}
+        @param s: the incoming data from the connection
+        
+        """
+        
         self.read(s)
 
     def _write_buffer(self, s):
+        """Write data back onto the buffer.
+        
+        @type s: C{string}
+        @param s: the data to rebuffer
+        
+        """
+        
         self.buffer = s+self.buffer
 
     def _read(self, s):
+        """Process the data that came in.
+        
+        @type s: C{string}
+        @param s: the (unencrypted) incoming data from the connection
+        
+        """
+        
         self.buffer += s
         while True:
             if self.closed:
@@ -210,9 +433,23 @@
                 return
 
     def connection_lost(self, connection):
+        """Close the connection and return the failure.
+        
+        @type connection: L{DebTorrent.SocketHandler.SingleSocket}
+        @param connection: the connection that was lost (not used)
+        
+        """
+        
         if not self.closed:
             self.closed = True
             self.resultfunc(False, self.downloadid, self.peerid, self.ip, self.port)
 
     def connection_flushed(self, connection):
+        """Do nothing.
+        
+        @type connection: L{DebTorrent.SocketHandler.SingleSocket}
+        @param connection: the connection that was flushed (not used)
+        
+        """
+        
         pass




More information about the Debtorrent-commits mailing list