2018-08-14 05:24:20 +00:00
/ *
2018-12-20 17:18:58 +00:00
HTML5 Speedtest v4 . 7 MPOT - Server selector
2018-08-14 05:24:20 +00:00
by Federico Dossena
https : //github.com/adolfintel/speedtest/
GNU LGPLv3 License
* /
//pings the specified URL, then calls the function result. Result will receive a parameter which is either the time it took to ping the URL, or -1 if something went wrong.
2018-12-20 17:18:58 +00:00
var PING _TIMEOUT = 1000 ;
var USE _PING _TIMEOUT = true ; //will be disabled on unsupported browsers
if ( /MSIE.(\d+\.\d+)/i . test ( navigator . userAgent ) ) { //IE11 doesn't support XHR timeout
USE _PING _TIMEOUT = false ;
}
2018-08-14 05:24:20 +00:00
function ping ( url , result ) {
var xhr = new XMLHttpRequest ( ) ;
var t = new Date ( ) . getTime ( ) ;
xhr . onload = function ( ) {
if ( xhr . responseText . length == 0 ) { //we expect an empty response
var instspd = new Date ( ) . getTime ( ) - t ; //rough timing estimate
try {
//try to get more accurate timing using performance API
var p = performance . getEntries ( ) ;
p = p [ p . length - 1 ] ;
var d = p . responseStart - p . requestStart ;
if ( d <= 0 ) d = p . duration ;
if ( d > 0 && d < instspd ) instspd = d ;
} catch ( e ) {
}
result ( instspd ) ;
} else result ( - 1 ) ;
} . bind ( this ) ;
xhr . onerror = function ( ) {
result ( - 1 ) ;
} . bind ( this ) ;
xhr . open ( "GET" , url ) ;
2018-12-20 17:18:58 +00:00
if ( USE _PING _TIMEOUT ) {
try {
xhr . timeout = PING _TIMEOUT ;
xhr . ontimeout = xhr . onerror ;
} catch ( e ) { }
}
2018-08-14 05:24:20 +00:00
xhr . send ( ) ;
}
//this function repeatedly pings a server to get a good estimate of the ping. When it's done, it calls the done function without parameters. At the end of the execution, the server will have a new parameter called pingT, which is either the best ping we got from the server or -1 if something went wrong.
var PINGS = 3 , //up to 3 pings are performed, unless the server is down...
SLOW _THRESHOLD = 500 ; //...or one of the pings is above this threshold
function checkServer ( server , done ) {
var i = 0 ;
server . pingT = - 1 ;
2018-08-18 08:00:30 +00:00
if ( server . server . indexOf ( location . protocol ) == - 1 ) done ( ) ; else {
var nextPing = function ( ) {
if ( i ++ == PINGS ) { done ( ) ; return ; }
ping ( server . server + server . pingURL , function ( t ) {
if ( t >= 0 ) {
if ( t < server . pingT || server . pingT == - 1 ) server . pingT = t ;
if ( t < SLOW _THRESHOLD ) nextPing ( ) ; else done ( ) ;
} else done ( ) ;
} . bind ( this ) ) ;
} . bind ( this ) ;
nextPing ( ) ;
}
2018-08-14 05:24:20 +00:00
}
/ * t h i s f u n c t i o n g o e s t h r o u g h a l i s t o f s e r v e r s , e a c h w i t h t h i s f o r m a t :
{
name : "User friendly name" ,
server : "http://yourBackend.com/" , < -- -- make sure there ' s a / at the end !
dlURL : "garbage.php" < -- -- - path to garbage . php or its replacement on the server
ulURL : "empty.php" < -- -- - path to empty . php or its replacement on the server
pingURL : "empty.php" < -- -- - path to empty . php or its replacement on the server . This is used to ping the server by this selector
getIpURL : "getIP.php" < -- -- - path to getIP . php or its replacement on the server
}
For each server , the ping is measured , then the server with the function result is called with the best server , or null if all the servers were down .
* /
function selectServer ( serverList , result ) {
var i = 0 ;
var done = function ( ) {
var bestServer = null ;
for ( var i = 0 ; i < serverList . length ; i ++ ) {
if ( serverList [ i ] . pingT != - 1 && ( bestServer == null || serverList [ i ] . pingT < bestServer . pingT ) ) bestServer = serverList [ i ] ;
}
result ( bestServer ) ;
} . bind ( this ) ;
var nextServer = function ( ) {
if ( i == serverList . length ) { done ( ) ; return ; }
checkServer ( serverList [ i ++ ] , nextServer ) ;
} . bind ( this ) ;
nextServer ( ) ;
}
/ *
this function is a faster version of selectServer that tests multiple servers concurrently . Useful for large server lists
* /
var CONCURRENCY = 4 ; //4 seems to be the safest value
function fastSelectServer ( serverList , result ) {
var serverLists = [ ] ;
for ( var i = 0 ; i < CONCURRENCY ; i ++ ) {
serverLists [ i ] = [ ] ;
}
for ( var i = 0 ; i < serverList . length ; i ++ ) {
serverLists [ i % CONCURRENCY ] . push ( serverList [ i ] ) ;
}
var completed = 0 ;
var bestServer = null ;
for ( var i = 0 ; i < CONCURRENCY ; i ++ ) {
selectServer ( serverLists [ i ] , function ( server ) {
if ( server != null ) {
if ( bestServer == null || server . pingT < bestServer . pingT ) bestServer = server ;
}
completed ++ ;
if ( completed == CONCURRENCY ) result ( bestServer ) ;
} . bind ( this ) ) ;
}
}