Using NSISdl to download from a random (or not random) mirror

From NSIS Wiki

Author: MoNKi (talk, contrib)


Description

I made this functions to download a file from a random mirror (for bandwidth balance), but you can also use it without the random feature.

How to Use

You are allowed to use a max of 10 mirrors, and the use is very simple, push the mirrors, push the number of mirrors previously pushed, push the file name, and call the function. It returns "success" if successfully downloaded, "cancel" if user canceled it, and the last error in other case.

Push "Mirror1"
[Push "Mirror2"]
[Push "Mirror3"]
...
[Push "Mirror10"]
Push NumberOfMirrors
Push "FileName"
Call DownloadFromRandomMirror
Pop $Result

(See the example code to learn how to use it without the random feature.)

The Script

Main Function

###################################################
# 
# Downloads a file from a list of mirrors
# (the fist mirror is selected at random)
#
# Usage:
# 	Push Mirror1
# 	[Push Mirror2]
# 	...
# 	[Push Mirror10]
#	Push NumMirrors		# 10 Max
#	Push FileName
#	Call DownloadFromRandomMirror
#	Pop Return
#
#	Returns the last NSISdl result
Function DownloadFromRandomMirror
	Exch $R1 #File name
	Exch
	Exch $R0 #Number of Mirrors
	Push $0
	Exch 3
	Pop $0	#Mirror 1
	IntCmpU "2" $R0 0 0 +4
		Push $1
		Exch 4
		Pop $1	#Mirror 2
	IntCmpU "3" $R0 0 0 +4
		Push $2
		Exch 5
		Pop $2	#Mirror 3
	IntCmpU "4" $R0 0 0 +4
		Push $3
		Exch 6
		Pop $3	#Mirror 4
	IntCmpU "5" $R0 0 0 +4
		Push $4
 
		Exch 7
		Pop $4	#Mirror 5
	IntCmpU "6" $R0 0 0 +4
		Push $5
		Exch 8
		Pop $5	#Mirror 6
	IntCmpU "7" $R0 0 0 +4
		Push $6
		Exch 9
		Pop $6	#Mirror 7
	IntCmpU "8" $R0 0 0 +4
		Push $7
		Exch 10
		Pop $7	#Mirror 8
	IntCmpU "9" $R0 0 0 +4
		Push $8
		Exch 11
		Pop $8	#Mirror 9
	IntCmpU "10" $R0 0 0 +4
		Push $9
		Exch 12
		Pop $9	#Mirror 10
	Push $R4
	Push $R2
	Push $R3
	Push $R5
	Push $R6
 
	StrCmp $RandomSeed "" 0 +2
		StrCpy $RandomSeed $HWNDPARENT   #init RandomSeed
 
	Push $RandomSeed
	Push $R0
	Call LimitedRandomNumber
	Pop $R3
	Pop $RandomSeed
 
	StrCpy $R5 "0"
MirrorsStart:
	IntOp $R5 $R5 + "1"
	StrCmp $R3 "0" 0 +3
		StrCpy $R2 $0
		Goto MirrorsEnd
	StrCmp $R3 "1" 0 +3
		StrCpy $R2 $1
		Goto MirrorsEnd
	StrCmp $R3 "2" 0 +3
		StrCpy $R2 $2
		Goto MirrorsEnd
	StrCmp $R3 "3" 0 +3
		StrCpy $R2 $3
		Goto MirrorsEnd
	StrCmp $R3 "4" 0 +3
		StrCpy $R2 $4
		Goto MirrorsEnd
	StrCmp $R3 "5" 0 +3
		StrCpy $R2 $5
		Goto MirrorsEnd
	StrCmp $R3 "6" 0 +3
		StrCpy $R2 $6
		Goto MirrorsEnd
	StrCmp $R3 "7" 0 +3
		StrCpy $R2 $7
		Goto MirrorsEnd
	StrCmp $R3 "8" 0 +3
		StrCpy $R2 $8
		Goto MirrorsEnd
	StrCmp $R3 "9" 0 +3
		StrCpy $R2 $9
		Goto MirrorsEnd
	StrCmp $R3 "10" 0 +3
		StrCpy $R2 $10
		Goto MirrorsEnd
 
MirrorsEnd:
	IntOp $R6 $R3 + "1"
	DetailPrint "Downloading from mirror $R6: $R2"
 
	NSISdl::download "$R2" "$R1"
	Pop $R4
	StrCmp $R4 "success" Success
	StrCmp $R4 "cancel" DownloadCanceled
	IntCmp $R5 $R0 NoSuccess
	DetailPrint "Download failed (error $R4), trying with other mirror"
	IntOp $R3 $R3 + "1"
	IntCmp $R3 $R0 0 MirrorsStart
	StrCpy $R3 "0"
	Goto MirrorsStart
 
DownloadCanceled:
	DetailPrint "Download Canceled: $R2"
	Goto End
NoSuccess:		
	DetailPrint "Download Failed: $R1"
	Goto End
Success:
	DetailPrint "Download completed."
End:
	Pop $R6
	Pop $R5
	Pop $R3
	Pop $R2
	Push $R4
	Exch
	Pop $R4
	Exch 2
	Pop $R1
	Exch 2
	Pop $0
	Exch
 
	IntCmpU "2" $R0 0 0 +4
		Exch 2	
		Pop $1
		Exch
	IntCmpU "3" $R0 0 0 +4
		Exch 2	
		Pop $2
		Exch
	IntCmpU "4" $R0 0 0 +4
		Exch 2	
		Pop $3
		Exch
	IntCmpU "5" $R0 0 0 +4
		Exch 2	
		Pop $4
		Exch
	IntCmpU "6" $R0 0 0 +4
		Exch 2	
		Pop $5
		Exch
	IntCmpU "7" $R0 0 0 +4
		Exch 2	
		Pop $6
		Exch
	IntCmpU "8" $R0 0 0 +4
		Exch 2	
		Pop $7
		Exch
	IntCmpU "9" $R0 0 0 +4
		Exch 2	
		Pop $8
		Exch
	IntCmpU "10" $R0 0 0 +4
		Exch 2	
		Pop $9
		Exch
	Pop $R0
FunctionEnd

Random Number Function

var RandomSeed		# The seed for the random number generator
 
###############################################################
#
# Returns a random number
#
# Usage:
# 	Push Seed (or previously generated number)
#	Call RandomNumber
#	Pop Generated Random Number
Function RandomNumber
	Exch $R0
 
	IntOp $R0 $R0 * "13"
	IntOp $R0 $R0 + "3"
	IntOp $R0 $R0 % "1048576" # Values goes from 0 to 1048576 (2^20)
 
	Exch $R0
FunctionEnd
 
####################################################
#
# Returns a random number between 0 and MaxValue-1
#
# Usage:
# 	Push Seed (or previously generated number)
#	Push MaxValue
#	Call RandomNumber
#	Pop Generated Random Number
#	Pop NewSeed
Function LimitedRandomNumber
	Exch $R0
	Exch
	Exch $R1
	Push $R2
	Push $R3
 
	StrLen $R2 $R0
	Push $R1
RandLoop:
	Call RandomNumber
	Pop $R1	#Random Number
	IntCmp $R1 $R0 0 NewRnd
	StrLen $R3 $R1	
	IntOp $R3 $R3 - $R2
	IntOp $R3 $R3 / "2"
	StrCpy $R3 $R1 $R2 $R3
	IntCmp $R3 $R0 0 RndEnd
NewRnd:
	Push $R1
	Goto RandLoop
RndEnd:
	StrCpy $R0 $R3
	IntOp $R0 $R0 + "0" #removes initial 0's
	Pop $R3
	Pop $R2
	Exch $R1
	Exch
	Exch $R0
FunctionEnd

Example Code

Name "Download From Mirror"
OutFile "Mirrors.exe"
 
var RandomSeed		# If you don't want a random mirror, remove this line
 
Section TestMirrors
	MessageBox MB_YESNO "This will download NSIS 2.0 Beta 3a from a random mirror, OK?" IDNO End
 
	# Downloads NSIS 2.0 Beta 3a from a max of 10 mirrors
 
	Push "http://belnet.dl.sourceforge.net/sourceforge/nsis/nsis20b3.exe"
	Push "http://cesnet.dl.sourceforge.net/sourceforge/nsis/nsis20b3.exe"
	Push "http://heanet.dl.sourceforge.net/sourceforge/nsis/nsis20b3.exe"
	Push "http://keihanna.dl.sourceforge.net/sourceforge/nsis/nsis20b3.exe"
	Push "http://easynews.dl.sourceforge.net/sourceforge/nsis/nsis20b3.exe"
	Push "http://twtelecom.dl.sourceforge.net/sourceforge/nsis/nsis20b3.exe"
	Push "http://flow.dl.sourceforge.net/sourceforge/nsis/nsis20b3.exe"
	Push "http://aleron.dl.sourceforge.net/sourceforge/nsis/nsis20b3.exe"
	Push "http://umn.dl.sourceforge.net/sourceforge/nsis/nsis20b3.exe"
	Push "http://unc.dl.sourceforge.net/sourceforge/nsis/nsis20b3.exe"
	Push 10
	Push "$EXEDIR\nsis20b3.exe"
	Call DownloadFromRandomMirror
	Pop $0
 
	StrCmp $0 "cancel" 0 +3
		MessageBox MB_OK "Download canceled"
		Goto End
	StrCmp $0 "success" 0 +3
		MessageBox MB_OK "Download OK"
		Goto End
	MessageBox MB_OK "Error $0"
	End:
 
SectionEnd
 
# Functions #######################################
 
###################################################
# 
# Downloads a file from a list of mirrors
# (the fist mirror is selected at random)
#
# Usage:
# 	Push Mirror1
# 	Push [Mirror2]
# 	...
# 	Push [Mirror10]
#	Push NumMirrors		# 10 Max
#	Push FileName
#	Call DownloadFromRandomMirror
#	Pop Return
#
#	Returns the NSISdl result
Function DownloadFromRandomMirror
	Exch $R1 #File name
	Exch
	Exch $R0 #Number of Mirros
	Push $0
	Exch 3
	Pop $0	#Mirror 1
	IntCmpU "2" $R0 0 0 +4
		Push $1
		Exch 4
		Pop $1	#Mirror 2
	IntCmpU "3" $R0 0 0 +4
		Push $2
		Exch 5
		Pop $2	#Mirror 3
	IntCmpU "4" $R0 0 0 +4
		Push $3
		Exch 6
		Pop $3	#Mirror 4
	IntCmpU "5" $R0 0 0 +4
		Push $4
		Exch 7
		Pop $4	#Mirror 5
	IntCmpU "6" $R0 0 0 +4
		Push $5
		Exch 8
		Pop $5	#Mirror 6
	IntCmpU "7" $R0 0 0 +4
		Push $6
		Exch 9
		Pop $6	#Mirror 7
	IntCmpU "8" $R0 0 0 +4
		Push $7
		Exch 10
		Pop $7	#Mirror 8
	IntCmpU "9" $R0 0 0 +4
		Push $8
		Exch 11
		Pop $8	#Mirror 9
	IntCmpU "10" $R0 0 0 +4
		Push $9
		Exch 12
		Pop $9	#Mirror 10
	Push $R4
	Push $R2
	Push $R3
	Push $R5
	Push $R6
 
	# If you don't want a random mirror, replace this block with:
	# StrCpy $R3 "0"
	# -----------------------------------------------------------
	StrCmp $RandomSeed "" 0 +2
		StrCpy $RandomSeed $HWNDPARENT  #init RandomSeed
 
	Push $RandomSeed
	Push $R0
	Call LimitedRandomNumber
	Pop $R3
	Pop $RandomSeed
	# -----------------------------------------------------------
 
	StrCpy $R5 "0"
MirrorsStart:
	IntOp $R5 $R5 + "1"
	StrCmp $R3 "0" 0 +3
		StrCpy $R2 $0
		Goto MirrorsEnd
	StrCmp $R3 "1" 0 +3
		StrCpy $R2 $1
		Goto MirrorsEnd
	StrCmp $R3 "2" 0 +3
		StrCpy $R2 $2
		Goto MirrorsEnd
	StrCmp $R3 "3" 0 +3
		StrCpy $R2 $3
		Goto MirrorsEnd
	StrCmp $R3 "4" 0 +3
		StrCpy $R2 $4
		Goto MirrorsEnd
	StrCmp $R3 "5" 0 +3
		StrCpy $R2 $5
		Goto MirrorsEnd
	StrCmp $R3 "6" 0 +3
		StrCpy $R2 $6
		Goto MirrorsEnd
	StrCmp $R3 "7" 0 +3
		StrCpy $R2 $7
		Goto MirrorsEnd
	StrCmp $R3 "8" 0 +3
		StrCpy $R2 $8
		Goto MirrorsEnd
	StrCmp $R3 "9" 0 +3
		StrCpy $R2 $9
		Goto MirrorsEnd
	StrCmp $R3 "10" 0 +3
		StrCpy $R2 $10
		Goto MirrorsEnd
 
MirrorsEnd:
	IntOp $R6 $R3 + "1"
	DetailPrint "Downloading from mirror $R6: $R2"
 
	NSISdl::download "$R2" "$R1"
	Pop $R4
	StrCmp $R4 "success" Success
	StrCmp $R4 "cancel" DownloadCanceled
	IntCmp $R5 $R0 NoSuccess
	DetailPrint "Download failed (error $R4), trying with other mirror"
	IntOp $R3 $R3 + "1"
	IntCmp $R3 $R0 0 MirrorsStart
	StrCpy $R3 "0"
	Goto MirrorsStart
 
DownloadCanceled:
	DetailPrint "Download Canceled: $R2"
	Goto End
NoSuccess:		
	DetailPrint "Download Failed: $R1"
	Goto End
Success:
	DetailPrint "Download completed."
End:
	Pop $R6
	Pop $R5
	Pop $R3
	Pop $R2
	Push $R4
	Exch
	Pop $R4
	Exch 2
	Pop $R1
	Exch 2
	Pop $0
	Exch
 
	IntCmpU "2" $R0 0 0 +4
		Exch 2	
		Pop $1
		Exch
	IntCmpU "3" $R0 0 0 +4
		Exch 2	
		Pop $2
		Exch
	IntCmpU "4" $R0 0 0 +4
		Exch 2	
		Pop $3
		Exch
	IntCmpU "5" $R0 0 0 +4
		Exch 2	
		Pop $4
		Exch
	IntCmpU "6" $R0 0 0 +4
		Exch 2	
		Pop $5
		Exch
	IntCmpU "7" $R0 0 0 +4
		Exch 2	
		Pop $6
		Exch
	IntCmpU "8" $R0 0 0 +4
		Exch 2	
		Pop $7
		Exch
	IntCmpU "9" $R0 0 0 +4
		Exch 2	
		Pop $8
		Exch
	IntCmpU "10" $R0 0 0 +4
		Exch 2	
		Pop $9
		Exch
	Pop $R0
FunctionEnd
 
###############################################################
#
# NOTE: If you don't want a random mirror, remove this Function
#
# Returns a random number
#
# Usage:
# 	Push Seed (or previously generated number)
#	Call RandomNumber
#	Pop Generated Random Number
Function RandomNumber
	Exch $R0
 
	IntOp $R0 $R0 * "13"
	IntOp $R0 $R0 + "3"
	IntOp $R0 $R0 % "1048576" # Values goes from 0 to 1048576 (2^20)
 
	Exch $R0
FunctionEnd
 
####################################################
#
# NOTE: If you don't want a random mirror, remove this Function
#
# Returns a random number between 0 and Max-1
#
# Usage:
# 	Push Seed (or previously generated number)
#	Push MaxValue
#	Call RandomNumber
#	Pop Generated Random Number
#	Pop NewSeed
Function LimitedRandomNumber
	Exch $R0
	Exch
	Exch $R1
	Push $R2
	Push $R3
 
	StrLen $R2 $R0
	Push $R1
RandLoop:
	Call RandomNumber
	Pop $R1	#Random Number
	IntCmp $R1 $R0 0 NewRnd
	StrLen $R3 $R1	
	IntOp $R3 $R3 - $R2
	IntOp $R3 $R3 / "2"
	StrCpy $R3 $R1 $R2 $R3
	IntCmp $R3 $R0 0 RndEnd
NewRnd:
	Push $R1
	Goto RandLoop
RndEnd:
	StrCpy $R0 $R3
	IntOp $R0 $R0 + "0" #removes initial 0's
	Pop $R3
	Pop $R2
	Exch $R1
	Exch
	Exch $R0
FunctionEnd
Personal tools
donate