# Written by bram cohen # see license.txt for license information
# File Name: Download.py # Readword Diary: 2004-9-4 # author: ZFive5 (Drone Hummer Shi [Lonely Boat Weng, Single Fishing Cold River Snow]) # # #着 上 来, I will now To analyze functions: #download (Params, D. Choosefile, D.Updatestatus, D.Finished, D. Error, Doneflag, 100, D.Newpath) # It is defined in Download.py. #
# Here import library, a bit like java in the import, here you can skip from zurllib import urlopen from urlparse import urljoin from btformats import check_message from Choker import Choker from Storage import Storage from StorageWrapper import StorageWrapper from Uploader import Upload from Downloader import Downloader from Connecter import Connecter from Encrypter import Encoder from RawServer import RawServer from Rerequester import Rerequester from DownloaderFeedback import DownloaderFeedback from RateMeasure import RateMeasure from CurrentRateMeasure import Measure from PiecePicker import PiecePicker from bencode import bencode, bdecode from sha import sha from os import path, makedirs from parseargs import parseargs , FormatDefinitions from Socket Import Error As SocketrRom Random Import Seed from Threading Import Thread, Event from Time Import Time Time: from OS Import GetPid Except Importerror: Def getPid (): Return 1
# Command line parameter Note list, when we run the BT client, a big dialog is popped up, # this is the information it above defaults = [('max_uploads', 7, "the maximum number of uploads to allow at once. "), ( 'keepalive_interval', 120.0, 'number of seconds to pause between sending keepalives'), (' download_slice_size ', 2 ** 14," How many bytes to query for per request. "), (' request_backlog ', 5, "how many requests to keep in a single pipe at once."), (' max_message_length ', 2 ** 23, "maximum length prefix encoding you'll accept over the wire - larger values get the connection dropped. "), ('IP', ''," IP to Report You "), ('MINPORT', 6881, 'Minimum Port to Listen on, Counts Up if Unavailable'), ('Maxport', 6999, 'Maximum Port to listen on'), ('responsefile', '', 'file the server response was store, alternative to url'), ('url', ',' url to get file from, alternative To Responsefile '), (' Saveas ',' ',' Local File Name to Save the file as, null indicates query user '), (' timeout ', 300.0,' to wait between closing sockets which nothing has been received on time '), (' timeout_check_interval ', 60.0,' time to wait between checking if any connections have Timed out '), (' max_slice_length ', 2 ** 17, "Maximum Length to send to peers, lar refests are ignored", (' max_rate_period ', 20.0, "
maximum amount of time to guess the current rate estimate represents "), ( 'bind', '', 'ip to bind to locally'), ( 'upload_rate_fudge', 5.0, 'time equivalent of writing to kernel-level TCP buffer, for rate adjustment '), (' display_interval ', .5,' time between updates of displayed information '), (' rerequest_interval ', 5 * 60,' time to wait between requesting more peers'), ( 'min_peers', 20 , 'minimum number of peers to not do rerequesting'), ( 'http_timeout', 60, 'number of seconds to wait before assuming that an http connection has timed out'), ( 'max_initiate', 40, 'number of peers at Which to stop initiating new connections'), ('Check_Hashes', 1,' WHETHER TO CHECK HASHES ON Disk '), (' max_upload_rate ', 0,' maximum kb / s to upload at, 0 means no limit '), 'snub_time', 30.0, "Seconds to Wait For Data TO COME IN OVER A Connection Before Assuming It's Semi-Permanently Choked" ), ('Spew', 0, "WHETHER TO DISPLAY Diagnostic Info To Stdout"), ('Rare of Downloads At Which To Switch from Random To Rarest First "), (' Min_uploads', 4, "the number of uploads to fill out to with extra optimistic unchokes"), ( 'rarest_first_priority_cutoff', 3, 'the number of peers which need to have a piece before other partials take priority over rarest first'), ( 'report_hash_failures', 0, "
WHETHER TO INFORM The User That Hash Failures Occur. "),] # Function: BT client's core function, mainly completing the function of downloading and uploading the function # parameters: Download (params, d." Choosefile, D.UpdateStatus, D.Finished, D.RROR, DONEFLAG, 100, D.NewPath statement, # we can analyze the meaning of each parameter # params: command line parameter Dictionary # filefunc: Select file path functions, corresponding The Choosefile member function of the main form is responsible for selecting the function of the file storage path. # Statusfunc: Status update function, the corresponding main form of the UpdateStatus member function, complete the update function on the window of the BT information. # Finfunc: Complete the processing Function, for the finished member function, completing the task, work after the task. # ErrorFunc: Error handler, Error member function, error handling # DONEFLAG: An event, associated with the main form # cols: command line parameters # pathfunc :? # Paramfunc :? # spewflag:?
def download (params, filefunc, statusfunc, finfunc, errorfunc, doneflag, cols, pathFunc = None, paramfunc = None, spewflag = Event ()): if len (params) == 0: # command line argument error errorfunc ( 'arguments Are - / n ' formatDefinitions (defaults, cols)) Return Try: # Analysis command line parameters config, args = parseargs (params, defaults, 0, 1) if args: # gets the value of the responsefile parameter, is the full seed file The path name, which has some error handles, can be skipped with if config.get ('responsefile', none) == None: rasse valueerror, 'Must Have Responsefile As Arg or Parameter, Not Both' if path.isfile (args [ 0]: config ['responsefile'] = args [0] Else: # Here you get the URL, the Torrent file open from the network config ['url'] = args [0] if (config ['responsefile'] == '') == (config ['URL'] == '): Raise ValueError,' NEED Responsefile or Url 'Except ValueError, E: Errorfunc (' Error: ' Str (E) ' / NRun with no args For parameter explanations') Return # Open seed files in different ways: if config ['responsefile']! = ': h = open (config [' responsefile '],' RB ') Else: h = urlopen (config [' url ']) Response = h.read () h.close () Except Ioerror, E: Errorfunc ('quoblem getting response info -' str (e)) Return
# Analyze the seed file try: # function BDECode (reponse), check_message (response) is a bit familiar, saying response = bdecode (response) Check_Message (response) EXCEPT VALUEERROR, E: E: ErrorFunc in << Read Bittorrent Code Diary 1 >> ("Got Bad File Info -" STR (e)) Return # Select the download storage file directory TRY: # Defines a function, which reminds me of the grammar of PL / 0, a bit recalling the compilation course design 5 years ago. .... Do not say nonsense DEF Make (f, forcedir = false): if not forcedir: f = path.Split (f) [0] IF f! = '' And not path.exists (f): Makedirs (f) )
# Get info information in the seed info = response ['info'] if info.has_key ('length'): # for a single file to store selection processing file_length = info ['length'] # Call Select Download Storage Function, Like Is the Save As dialog box in the VC, the language is connected .... file = filefunc (INFO ['Name'], File_Length, config ['saveas'], false) if file is none: return # generation file directory MAKE File # Generate a list of files and size FILES = [(file, file_length)] else: # 非 非 单 文件 文件 目 非 选择 处理 处理 [[[处理 处理 处理 处理 处理 处理 处理 处理 处理 处理 处理 处理 处理 目 目 处理 处理 处理 处理 处理 处理 处理Length '] # 同, here I don't want to talk nonsense File = FILEFUNC (Info [' Name '], File_length, config [' saveas'], true) If File IS None: Return # if this path exists, and no files from THE INFO DICT EXIST, We Assume it's a new Download and # The user want to create a new directory with the default name # Generate the corresponding storage directory EXISTING = 0 if path.exists (file): for x in info ['files']: if path.exists (path.join (file, x ['Path'] [0])): EXISG = 1 if not existing: File = path.join (file, info ['name']) make (file, true) # alert the ui one possible change in path if pathfunc! = none: pathfunc (file) # Generate a list of files and sizes, generate Corresponding subdirectory Files = [] for x in info ['files "
]: N = file for i in x ['Path']: n = path.join (n, i) files.Append ((N, x ['length'])) Make (n) Except Osterror, E: Errorfunc ("COULDN'T Allocate Dir -" STR (E)) Return # Continue Finflag = Event () Ann = [None] myid = (CHR (0) * 12) SHA (REPR ()) '' Str ())). Digest () [- 8:] #initialize the Basic Random Number Generator. Python Infunction Seed (MyID) # gets a list of Sha1 summary, generate a list PIECES = [INFO ['PIECES '] [x: x 20] for x xrange (0, LEN (INFO [' PIECES ']), 20)] # Defines Fail Processing Function DEF FAILED (Reason, Errorfunc = Errorfunc, Doneflag = DONEFLAG): DONEFLAG. SET () IF REASON IS Not None: ErrorFunc (Reason) # Defines a TCP server class, this class's source code will then list the analysis Rawserver = Rawserver (DoneFlag, Config ['Timeout_Check_Interval'], config ['Timeout'], Errorfunc = errorfunc) TRY: TRY: # 这个 I don't know what to do now, then analyze Storage = Storage (Files, Open, Path.exists, path.getsize) Except Ioerror, E: ERRORFUNC ('Trouble Accessing Files -' Str (E)) Return # defines a completion processing function DEF FINISHED (Finfunc = Finfunc, finflag = finflag, ann = ann, storage = storage, errorfunc = errorfunc): finflag.set () try: storage.set_readonly () except (IOError, OSError), e: errorfunc ( 'trouble setting readonly at end -'
Str (e)) IF ANN [0] IS Not None: Ann [0] (1) Finfunc () RM = [None] # Data Failed Handling Function DEF DATA_FLUNKED (Amount, Rm = RM, Errorfunc = Errorfunc, Report_hash_Failures = Config ['Report_hash_Failures']): IF RM [0] IS Not None: RM [0] (Amount) IF Report_hash_Failures: ErrorFunc ('a piece failed hash check, re-downloading it')
# I do not know this is doing, after reanalysis storagewrapper = StorageWrapper (storage, config [ 'download_slice_size'], pieces, info [ 'piece length'], finished, failed, statusfunc, doneflag, config [ 'check_hashes' ], DATA_FLUNKED) Except ValueError, E: Failed ('Bad Data -' Str (E)) Except Ioerror, E: Failed ('Ioerror -' STR (E)) ifeflag.isset (): Return # bundle server Port, minport <= listen_port <= maxport e = 'maxport less tour "for listen_port in xrange (config [' minport '], config [' maxport '] 1): Try: Rawserver.bind Listen_Port, Config ['Bind']) Break Except SocketError, E: Pass Else: Errorfunc ("COULDN '' Listen -" Str (E)) Return
# Write here I intend to stop, now the brain has too many question mark, what is the two classes like Rawserver? # I haven't thought about it now, I am going to see their definitions first. . . .