Read BitTorrent code diary 3

Source: Internet
Author: User

#! /Usr/bin/ENV Python

# Written by Bram Cohen and Myers carpenter
# See license.txt for license information
#
# File name: btdownloadgui. py
# Code reading diary: 2004-9-2
# Pen: zfive5
#
# Today, I decided to open the seed file to start analysis on the BT client.
# For better understanding, I analyzed the source code in the window2000 environment, and double-click. torrent under the Resource Manager.
# File, then we will see the BT client that we are all very familiar with. Let's select the file directory ....
# Perception tells me that the seed file name is passed into the BT client through a parameter call and opened registration through regedit
# Table we can find the following clues:
#
# Windows Registry Editor Version 5.00
#
# [Hkey_classes_root/. torrent]
##= "BitTorrent"
# "Content type" = "application/X-BitTorrent"
#
# [Hkey_classes_root/BitTorrent]
##= "Torrent file"
# "Editflags" = HEX: 00, 01,00
#
# [Hkey_classes_root/BitTorrent/Shell]
# @ = "Open"
#
# [Hkey_classes_root/BitTorrent/Shell/edit]
##= "Edit torrent with torrentedit"
#
# [Hkey_classes_root/BitTorrent/Shell/edit/command]
# @ = "/" C: // program files // btdwv // torrentedit.exe/"-- torrentfile/" % 1 /""
#
# [Hkey_classes_root/BitTorrent/Shell/Open]
#
# [Hkey_classes_root/BitTorrent/Shell/Open/command]
# @ = "/" C: // program files // btdwv // btdownloadgui.exe/"-- responsefile/" % 1 /""
#
# The system is executed:
# C:/program files/btdwv/btdownloadgui.exe -- responsefile E:/help. CHM. torrent
#
# Analyze the following file now...
# You can directly go to the definition section of class btwxapp (wxapp ).
#

From sys import argv
From BitTorrent import version
From BitTorrent. Download import download
From btdownloadheadless import print_spew
From threading import event, thread
From OS. Path import join, split, exists
From OS import getcwd
From wxpython. wx import *
From time import strftime, time
From webbrowser import open_new
From traceback import print_exc

# Calculate the time function second-> (hour: minute: second)
Def hours (n ):
If n =-1:
Return''
If n = 0:
Return 'complete! '
N = int (N)
H, r = divmod (n, 60*60)
M, SEC = divmod (R, 60)
If H> 1000000:
Return''
If H> 0:
Return '% d hour % 02d min % 02d sec' % (H, M, Sec)
Else:
Return '% D min % 02d sec' % (M, Sec)

Wxevt_invoke = wxneweventtype ()

# I am not clear about events or other things. You can skip this step.
Def evt_invoke (Win, func ):
Win. Connect (-1,-1, wxevt_invoke, func)

# Same as above
Class invokeevent (wxpyevent ):
Def _ init _ (self, func, argS, kwargs ):
Wxpyevent. _ init _ (Self)
Self. seteventtype (wxevt_invoke)
Self. func = func
Self. ARGs = ARGs
Self. kwargs = kwargs

# Download the main form class. This is also true through perception.
Class downloadinfoframe:

# This is a class constructor.
Def _ init _ (self, flag ):
Frame = wxframe (none,-1, 'bittorrent '+ version + 'Download', size = wxsize (400,250 ))
Self. Frame = frame
Self. Flag = Flag
Self. uiflag = event ()
Self. Fin = false
Self. last_update_time = 0
Self. showing_error = false

Panel = wxpanel (frame,-1)
Colsizer = wxflexgridsizer (Cols = 1, vgap = 3)

Fnsizer = wxboxsizer (wxhorizontal)

Self. filenametext = wxstatictext (panel,-1, '', style = wxalign_left)
Fnsizer. Add (self. filenametext, 1, wxalign_bottom)
Self. abouttext = wxstatictext (panel,-1, 'about', style = wxalign_right)
Self. abouttext. setforegroundcolour ('blue ')
Self. abouttext. setfont (wxfont (14, wxnormal, true ))
Fnsizer. Add (self. abouttext, 0, wxexpand)
Colsizer. Add (fnsizer, 0, wxexpand)

Self. Gauge = wxgauge (panel,-1, range = 1000, style = wxga_smooth)
Colsizer. Add (self. gauge, 0, wxexpand)

Gridsizer = wxflexgridsizer (Cols = 2, vgap = 3, hgap = 8)

Gridsizer. Add (wxstatictext (panel,-1, 'Estimated time left :'))
Self. timeesttext = wxstatictext (panel,-1 ,'')
Gridsizer. Add (self. timeesttext, 0, wxexpand)

Gridsizer. Add (wxstatictext (panel,-1, 'Download :'))
Self. filedesttext = wxstatictext (panel,-1 ,'')
Gridsizer. Add (self. filedesttext, 0, wxexpand)

Gridsizer. addgrowablecol (1)

Rategridsizer = wxflexgridsizer (Cols = 4, vgap = 3, hgap = 8)

Rategridsizer. Add (wxstatictext (panel,-1, 'Download rate :'))
Self. downratetext = wxstatictext (panel,-1 ,'')
Rategridsizer. Add (self. downratetext, 0, wxexpand)

Rategridsizer. Add (wxstatictext (panel,-1, 'downloaded :'))
Self. downtotaltext = wxstatictext (panel,-1 ,'')
Rategridsizer. Add (self. downtotaltext, 0, wxexpand)

Rategridsizer. Add (wxstatictext (panel,-1, 'upload rate :'))
Self. upratetext = wxstatictext (panel,-1 ,'')
Rategridsizer. Add (self. upratetext, 0, wxexpand)


Rategridsizer. Add (wxstatictext (panel,-1, 'uploaded :'))
Self. uptotaltext = wxstatictext (panel,-1 ,'')
Rategridsizer. Add (self. uptotaltext, 0, wxexpand)

Rategridsizer. addgrowablecol (1)
Rategridsizer. addgrowablecol (3)


Colsizer. Add (gridsizer, 0, wxexpand)
Colsizer. Add (rategridsizer, 0, wxexpand)
Colsizer. Add (50, 50, 0, wxexpand)
Self. cancelbutton = wxbutton (panel,-1, 'cancel ')
Colsizer. Add (self. cancelbutton, 0, wxalign_center)
Colsizer. addgrowablecol (0)
Colsizer. addgrowablerow (3)

Border = wxboxsizer (wxhorizontal)
Border. Add (colsizer, 1, wxexpand | wxall, 4)
Panel. setsizer (Border)
Panel. setautolayout (true)

Evt_left_down (self. abouttext, self. Donate)
Evt_close (frame, self. Done)
Evt_button (frame, self. cancelbutton. GETID (), self. Done)
Evt_invoke (frame, self. oninvoke)
Self. Frame. Show ()

# Some event processing functions and auxiliary functions below
Def donate (self, event ):
Thread (target = self. donate2). Start ()

Def donate2 (Self ):
Open_new ('HTTP: // bitconjurer.org/bittor#/donate.html ')

Def oninvoke (self, event ):
If not self. uiflag. isset ():
Apply (event. func, event. ARGs, event. kwargs)

Def invokelater (self, func, argS = [], kwargs = {}):
If not self. uiflag. isset ():
Wxpostevent (self. Frame, invokeevent (func, argS, kwargs ))

Def updatestatus (self, d ):
If (self. last_update_time + 0.1 <time () and not self. showing_error) or D. get ('fractiondone') in (0.0, 1.0) or D. has_key ('active '):
Self. invokelater (self. onupdatestatus, [d])

Def onupdatestatus (self, d ):
Try:
If D. has_key ('spew '):
Print_spew (d ['spew'])
Activity = D. Get ('active ')
Fractiondone = D. Get ('fractiondone ')
Timeest = D. Get ('timeest ')
Downrate = D. Get ('downrate ')
Uprate = D. Get ('uprate ')
Downtotal = D. Get ('Download ')
Uptotal = D. Get ('uptotal ')
If activity is not none and not self. Fin:
Self. timeesttext. setlabel (activity)
If fractiondone is not none and not self. Fin:
Self. gauge. setvalue (INT (fractiondone * 1000 ))
Self. Frame. settitle ('% d % s-BitTorrent % s' % (INT (fractiondone * 100), self. filename, Version ))
If timeest is not none:
Self. timeesttext. setlabel (hours (timeest ))
If downrate is not none:
Self. downratetext. setlabel ('%. 0f kib/s' % (float (downrate)/(1 <10 )))
If uprate is not none:
Self. upratetext. setlabel ('%. 0f kib/s' % (float (uprate)/(1 <10 )))
If downtotal is not none:
Self. downtotaltext. setlabel ('%. 1f m' % (downtotal ))
If uptotal is not none:
Self. uptotaltext. setlabel ('%. 1f m' % (uptotal ))
Self. last_update_time = Time ()
Except t:
Print_ex ()

Def finished (Self ):
Self. Fin = true
Self. invokelater (self. onfinishevent)

Def failed (Self ):
Self. Fin = true
Self. invokelater (self. onfailevent)

Def error (self, errormsg ):
If not self. showing_error:
Self. invokelater (self. onerrorevent, [errormsg])

Def onfinishevent (Self ):
Self. timeesttext. setlabel ('Download succeeded! ')
Self. cancelbutton. setlabel ('close ')
Self. gauge. setvalue (1000)
Self. Frame. settitle ('% s-upload-BitTorrent % s' % (self. filename, Version ))
Self. downratetext. setlabel ('')

Def onfailevent (Self ):
Self. timeesttext. setlabel ('failed! ')
Self. cancelbutton. setlabel ('close ')
Self. gauge. setvalue (0)
Self. downratetext. setlabel ('')

Def onerrorevent (self, errormsg ):
Self. showing_error = true
DLG = wxmessagedialog (self. Frame, message = errormsg,
Caption = 'Download error', style = wxok | wxicon_error)
DLG. Fit ()
DLG. Center ()
DLG. showmodal ()
Self. showing_error = false

Def choosefile (self, default, size, saveas, DIR ):
If saveas:
Return saveas
F = event ()
Bucket = [none]
Self. invokelater (self. onchoosefile, [default, bucket, F, size, Dir])
F. Wait ()
Return bucket [0]

Def onchoosefile (self, default, bucket, F, size, DIR ):
If dir:
DL = wxdirdialog (self. Frame, 'Choose a directory to save to, pick a partial download to resume ',

Join (getcwd (), default), style = wxdd_default_style | wxdd_new_dir_button)
Else:
DL = wxfiledialog (self. Frame, 'Choose file to save as, pick a partial download to resume ', '', default,' *. * ', wxsave)
If DL. showmodal ()! = Wxid_ OK:
Self. Done (none)
Else:
Bucket [0] = DL. getpath ()
Self. filenametext. setlabel ('% s (%. 1f MB)' % (default, float (size)/(1 <20 )))
Self. timeesttext. setlabel ('starting up ...')
Self. filedesttext. setlabel (DL. getpath ())
Self. filename = default
Self. Frame. settitle (default + '-BitTorrent' + version)
F. Set ()

Def newpath (self, PATH ):
Self. filedesttext. setlabel (PATH)

Def done (self, event ):
Self. uiflag. Set ()
Self. Flag. Set ()
Self. Frame. Destroy ()

# This is the BT app class. The starting position of Bt, and Params is the command line parameter.
Class btwxapp (wxapp ):
Def _ init _ (self, X, Params ):
Self. Params = Params
Wxapp. _ init _ (self, X)

# This member function is a bit like the bool ctestv1app: initinstance () member function in MFC (this is the result of my years of VC use)
# The preceding main form class is created and a Thread class is started.
#
Def oninit (Self ):
Doneflag = event ()
D = downloadinfoframe (doneflag)
Self. settopwindow (D. Frame)
Thread = thread (target = Next, argS = [self. Params, D, doneflag])
Thread. setdaemon (false)
Thread. Start ()
Return 1

# Here is the entry function of the BT client.
Def run (Params ):
Try:
APP = btwxapp (0, Params)
App. mainloop ()
Except t:
Print_exc ()

# Thread processing functions, which is also the core process of BT
Def next (Params, D, doneflag ):
Try:
# This section is a bit confusing
P = join (split (argv [0]) [0], 'donated ')
If not exists (P) and long (Time () % 3 = 0:
Open_new ('HTTP: // bitconjurer.org/bittor#/donate.html ')
DLG = wxmessagedialog (D. Frame, 'bittorrent is donation supported software. '+

'Please go to the donation page (which shocould be appearing for you now) and make a donation from there. '+

'Or you can click NO and donate later./N/nhave you made a donation yet? ',
'Donate! ', Wxyes_no | wxicon_information | wxno_default)
If DLG. showmodal () = wxid_yes:
DLG. Destroy ()
DLG = wxmessagedialog (D. Frame, 'Thanks for your donation! You will no longer be shown donation requests./N/N' +

"If you haven't actually made a donation and are feeling guilty (as you shoshould !) You can always get to "+

"The donation page by clicking the 'About' link in the upper-right corner of the main BitTorrent window and" +

'Donating from there. ', 'Thanks! ', Wxok)
DLG. showmodal ()
DLG. Destroy ()
Try:
Open (p, 'wb '). Close ()
Handle t ioerror, E:
DLG = wxmessagedialog (D. Frame, "Sorry, but I couldn't set the flag to not ask you for donations in the future-" + STR (e ),
'Sorry! ', Wxok | wxicon_error)
DLG. showmodal ()
DLG. Destroy ()
Else:
DLG. Destroy ()

# This is another function we will talk about below.
Download (Params, D. choosefile, D. updatestatus, D. Finished, D. error, doneflag, 100, D. newpath)
If not D. Fin:
D. Failed ()
Except t:
Print_exc ()

# It calls the run function. The input command line parameter is -- responsefile E:/help. CHM. torrent.
If _ name _ = '_ main __':
Run (argv [1:])

# Analyze it here (to be continued)

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.