Read BitTorrent code diary 4

Source: Internet
Author: User
Tags file info

# Written by Bram Cohen
# See license.txt for license information

# File name: Download. py
# Code reading diary: 2004-9-4
# Pen: zfive5
#
# In the previous section, I naturally want to analyze functions:
# Download (Params, D. choosefile, D. updatestatus, D. Finished, D. error, doneflag, 100, D. newpath)
# Its definition is in download. py.
#

# Import to the database here, a bit like the import in Java, which can be skipped here
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 socketerror
From Random import Seed
From threading import thread, event
From time import time
Try:
From OS import getpid
Failed t importerror:
Def getpid ():
Return 1

# Command line parameter comment list. When we directly run the BT client, a large dialog box is displayed,
# This is the information above it
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 have to the tracker ."),
('Minport', 6881, 'minimum port to listen on, counts up if unavailable '),
('Maxport', 6999, 'maximum port to listen on '),
('Responsefile ','',
'File the server response was stored in, 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,
'Time to wait between closing sockets which nothing has been encrypted ed on '),
('Timeout _ check_interval ', 60.0,
'Time to wait between checking if any connections have timed out '),
('Max _ slice_length ', 2 ** 17,
"Maximum length slice to send to peers, larger requests 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 "),
('Rarest _ first_cutoff ', 4,
"Number 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. They're non-fatal ."),
]

# Function: core functions of the BT client, mainly including downloading and uploading
# Parameter: Use the download (Params, D. choosefile, D. updatestatus, D. Finished, D. error, doneflag, 100, D. newpath) Statement in the preceding section,
# We can analyze the meaning of each parameter.
# Params: Command Line Parameter dictionary
# Filefunc: select the file path function, which corresponds to the choosefile member function of the main form. This function selects the file storage path.
# Statusfunc: Status update function, which corresponds to the updatestatus member function of the main form to update BT information in the window.
# Finfunc: complete the processing function. Complete the work after the finished member function.
# Errorfunc: error handling function, error handling for the error member function
# Doneflag: An event associated with the main form
# Cols: Number of 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 parameter error
Errorfunc ('arguments are-/N' + formatdefinitions (defaults, cols ))
Return
Try:
# Analyze command line parameters
Config, argS = parseargs (Params, defaults, 0, 1)
If ARGs:
# Obtain the value of the responsefile parameter, that is, the full path name of the seed file. Some errors are processed and can be skipped.
If config. Get ('responsefile', none) = none:
Raise valueerror, 'must have responsefile as Arg or parameter, not both'
If path. isfile (ARGs [0]):
Config ['responsefile'] = ARGs [0]
Else:
# Here we get the URL to open the torrent file from the network.
Config ['url'] = ARGs [0]
If (config ['responsefile'] = '') = (config ['url'] = ''):
Raise valueerror, 'need responsefile or url'
Failed t valueerror, E:
Errorfunc ('error: '+ STR (e) +'/nrun with no ARGs for parameter explanations ')
Return

# Opening a seed file in different ways
Try:
If config ['responsefile']! = '':
H = open (config ['responsefile'], 'rb ')
Else:
H = urlopen (config ['url'])
Response = H. Read ()
H. Close ()
Handle t ioerror, E:
Errorfunc ('problem getting response Info-'+ STR (e ))
Return

# Analysis of seed files
Try:
# Function bdecode (reponse), check_message (response) is a bit familiar, as mentioned in <read BitTorrent code diary 1>
Response = bdecode (response)
Check_message (response)
Failed t valueerror, E:
Errorfunc ("got bad file info-" + STR (e ))
Return

# Select a directory for downloading and storing files
Try:
# Define a function, which reminds me of the PL/0 syntax. I think back to the compilation course design five years ago.
Def make (F, forcedir = false ):
If not forcedir:
F = path. Split (f) [0]
If F! = ''And not path. exists (f ):
Makedirs (f)

# Obtain the info information in the seed.
Info = response ['info']
If Info. has_key ('length '):
# Selecting and processing Directory storage for a single file
File_length = info ['length']
# Call and select to download and store the function, such as the Save As dialog box in VC. The language is the same ....
File = filefunc (info ['name'], file_length, config ['saveas'], false)
If file is none:
Return
# Generate a file directory
Make (file)

# Generate a list corresponding to the file size
Files = [(file, file_length)]
Else:
# Directory storage selection for non-single files
File_length = 0
For X in info ['files']:
File_length + = x ['length']
# Same as above. I don't want to talk nonsense here.
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 wants to create a new directory with the default name
# Generate a storage directory
Existing = 0
If path. exists (File ):
For X in info ['files']:
If path. exists (path. Join (file, X ['path'] [0]):
Existing = 1
If not existing:
File = path. Join (file, info ['name'])

Make (file, true)

# Alert the UI to any possible change in Path
If pathfunc! = None:
Pathfunc (file)

# Generate a list of files corresponding to the size and generate corresponding subdirectories
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)
Counter t oserror, E:
Errorfunc ("couldn't allocate Dir-" + STR (e ))
Return

# Continue
Finflag = event ()
Ann = [none]
Myid = (CHR (0) * 12) + Sha (Repr (Time () + ''+ STR (getpid (). Digest () [-8:]

# Initialize the basic random number generator. Python infunction
Seed (myid)

# Obtain the sha1 digest of each pieces and generate a list
Pieces = [info ['pieces'] [x: x + 20] for X in xrange (0,
Len (info ['pieces']), 20)]

# Define failure handling functions
Def failed (reason, errorfunc = errorfunc, doneflag = doneflag ):
Doneflag. Set ()
If reason is not none:
Errorfunc (reason)

# Define a TCP server class. The source code of this class will be listed later for analysis.
Rawserver = rawserver (doneflag, config ['timeout _ check_interval '], config ['timeout'], errorfunc = errorfunc)
Try:
Try:
# I don't know what this is. I will analyze it later.
Storage = storage (files, open, path. exists, path. getsize)
Handle t ioerror, E:
Errorfunc ('trouble accessing files-'+ STR (e ))
Return

# Define a completed processing function
Def finished (finfunc = finfunc, finflag = finflag,
Ann = Ann, storage = storage, errorfunc = errorfunc ):
Finflag. Set ()
Try:
Storage. set_readonly ()
Handle T (ioerror, oserror), E:
Errorfunc ('trouble setting readonly at end-'+ STR (e ))
If Ann [0] is not none:
Ann [0] (1)
Finfunc ()

Rm = [none]

# Data failure processing 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 don't know what this is. I will analyze it later.
Storagewrapper = storagewrapper (storage,
Config ['Download _ slice_size '], pieces,
Info ['piece length'], finished, failed,
Statusfunc, doneflag, config ['check _ hashes '], data_flunked)
Failed t valueerror, E:
Failed ('bad data-'+ STR (e ))
Handle t ioerror, E:
Failed ('ioerror-'+ STR (e ))
If doneflag. isset ():
Return

# Bind the server port, minport <= listen_port <= maxport
E = 'maxport less than minport-no ports to Check'
For listen_port in xrange (config ['minport'], config ['maxport'] + 1 ):
Try:
Rawserver. BIND (listen_port, config ['bind'])
Break
T socketerror, E:
Pass
Else:
Errorfunc ("couldn't listen-" + STR (e ))
Return

# I plan to stop writing it here. Now I have too many question marks in my mind. What are the two classes like rawserver and storage?
# I am not thinking about it now. I plan to look at their definitions first ....

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.