commit
432aac6505
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1 +1,2 @@
|
|||
ugly.bat
|
||||
wishlist.txt
|
||||
|
|
12
README.md
12
README.md
|
@ -26,17 +26,25 @@ Only modern browsers are supported (IE11, latest Edge, latest Chrome, latest Fir
|
|||
## Quick installation videos
|
||||
* [Debian 9.0 with Apache](https://fdossena.com/?p=speedtest/quickstart_deb.frag)
|
||||
* [Windows Server 2016 with IIS](https://fdossena.com/?p=speedtest/quickstart_win.frag)
|
||||
* [Ubuntu (External)](https://freedif.org/how-to-install-selfhosted-speedtest)
|
||||
|
||||
Also, here's an [example config on Ubuntu 16 LTS](https://github.com/adolfintel/speedtest/issues/50)
|
||||
|
||||
## How to use in your site
|
||||
See the examples or doc.md
|
||||
* See the examples
|
||||
* [Read the wiki](https://github.com/adolfintel/speedtest/wiki)
|
||||
* Read doc.md
|
||||
|
||||
## Docker
|
||||
Please see the ```docker``` branch
|
||||
|
||||
## Node.js backend
|
||||
A Node.js implementation is available in the ```node``` branch, maintained by [dunklesToast](https://github.com/dunklesToast).
|
||||
|
||||
## Donate
|
||||
If you want to support this project, you can [send a donation via PayPal](https://www.paypal.me/sineisochronic).
|
||||
[![Donate with Liberapay](https://liberapay.com/assets/widgets/donate.svg)](https://liberapay.com/fdossena/donate)
|
||||
[Donate with PayPal](https://www.paypal.me/sineisochronic)
|
||||
Send ETH at this address: ```0x8A5273d4e2618c4cff2C62d8EB731701FceEd8E3```
|
||||
|
||||
## License
|
||||
Copyright (C) 2016-2018 Federico Dossena
|
||||
|
|
29
doc.md
29
doc.md
|
@ -1,7 +1,7 @@
|
|||
# HTML5 Speedtest
|
||||
|
||||
> by Federico Dossena
|
||||
> Version 4.5.3, February 23, 2018
|
||||
> Version 4.5.5, April 25, 2018
|
||||
> [https://github.com/adolfintel/speedtest/](https://github.com/adolfintel/speedtest/)
|
||||
|
||||
|
||||
|
@ -237,6 +237,10 @@ w.postMessage('start '+JSON.stringify(params))
|
|||
* Default: `3`
|
||||
* Recommended: `>=1`
|
||||
* Default override: 1 on Firefox if enable_quirks is true
|
||||
* __xhr_ul_blob_megabytes__: size in megabytes of the blobs sent during the upload test
|
||||
* Default: `20`
|
||||
* Default override: 4 on Chromium-based mobile browsers (limitation introduced around version 65). This will be forced
|
||||
* Default override: IE11 and Edge currently use a different method for the upload test. This parameter is ignored
|
||||
* __xhr_multistreamDelay__: how long should the multiple streams be delayed (in ms)
|
||||
* Default: `300`
|
||||
* Recommended: `>=100`, `<=700`
|
||||
|
@ -312,21 +316,21 @@ You need to start the test with your replacements like this:
|
|||
w.postMessage('start {"url_dl": "newGarbageURL", "url_ul": "newEmptyURL", "url_ping": "newEmptyURL", "url_getIp": "newIpURL"}')
|
||||
```
|
||||
## Telemetry
|
||||
Telemetry currently requires PHP and either MySQL, PostgreSQL or SQLite.
|
||||
Telemetry currently requires PHP and either MySQL, PostgreSQL or SQLite. Alternatively, it is possible to save to a CSV file.
|
||||
To set up the telemetry, we need to do 4 things:
|
||||
* copy `telemetry.php` and `telemetry_settings.php`
|
||||
* edit `telemetry_settings.php` to add your database settings
|
||||
* edit `telemetry_settings.php` to add your database or CSV settings
|
||||
* create the database
|
||||
* enable telemetry
|
||||
|
||||
### Creating the database
|
||||
This step is only for MySQL and PostgreSQL. Skip this if you want to use SQLite.
|
||||
This step is only for MySQL and PostgreSQL.
|
||||
Log into your database using phpMyAdmin or a similar software and import the appropriate sql file into an empty database. For MySQL databases use `telemetry_mysql.sql` and for PostgreSQL databases use `telemetry_postgesql.sql`.
|
||||
If you see a table called `speedtest_users`, empty, you did it right.
|
||||
|
||||
### Configuring `telemetry.php`
|
||||
Open telemetry_settings.php with notepad or a similar text editor.
|
||||
Set your preferred database, ``$db_type="mysql";``, ``$db_type="sqlite";`` or ``$db_type="postgresql";``
|
||||
Set your preferred database, ``$db_type="mysql";``, ``$db_type="sqlite";``, ``$db_type="postgresql";`` or or ``$db_type="csv";``
|
||||
If you choose to use Sqlite3, you must set the path to your database file:
|
||||
```php
|
||||
$Sqlite_db_file = "../telemetry.sql";
|
||||
|
@ -348,6 +352,13 @@ $PostgreSql_hostname="DB_HOSTNAME"; //database address, usually localhost
|
|||
$PostgreSql_databasename="DB_NAME"; //the name of the database where you loaded telemetry_postgresql.sql
|
||||
```
|
||||
|
||||
If you choose to use a CSV file, you must set the Csv_File and timezone variables.
|
||||
```php
|
||||
$Csv_File="myReportFile.csv";
|
||||
$timezone='Europe/Paris';
|
||||
```
|
||||
__Note__: CSV currently only supports basic telemetry, the log will not be saved
|
||||
|
||||
### Enabling telemetry
|
||||
Edit your test page; where you start the worker, you need to specify the `telemetry_level`.
|
||||
There are 3 levels:
|
||||
|
@ -366,7 +377,7 @@ Also, see example-telemetry.html
|
|||
At the moment there is no front-end to see the telemetry data; you can connect to the database and see the collected results in the `speedtest_users` table.
|
||||
|
||||
## Troubleshooting
|
||||
These are the most common issues reported by users, and how to fix them. If you still need help, contact me at [dosse91@paranoici.org](mailto:dosse91@paranoici.org).
|
||||
These are the most common issues reported by users, and how to fix them. If you still need help, contact me at [info@fdossena.com](mailto:info@fdossena.com).
|
||||
|
||||
#### Download test gives very low result
|
||||
Are garbage.php and empty.php (or your replacements) reachable?
|
||||
|
@ -393,7 +404,7 @@ Make sure your server is sending the ```Connection:keep-alive``` header
|
|||
* On IE11, a same origin policy error is erroneously triggered under unknown conditions. Seems to be related to running the test from unusual URLs like a top level domain (for instance http://abc/speedtest). These are bugs in IE11's implementation of the same origin policy, not in the speedtest itself.
|
||||
* On IE11, under unknown circumstances, on some systems the test can only be run once, after which speedtest_worker.js will not be loaded by IE until the browser is restarted. This is a rare bug in IE11.
|
||||
### Firefox-Specific
|
||||
* On some Linux systems with hardware acceleration turned off, the page rendering makes the browser lag, reducing the accuracy of the ping/jitter test
|
||||
* On some Linux systems with hardware acceleration turned off, the page rendering makes the browser lag, reducing the accuracy of the ping/jitter test, and potentially even the download and upload tests on very fast connections.
|
||||
|
||||
## Making changes
|
||||
Since this is an open source project, you can modify it.
|
||||
|
@ -406,7 +417,7 @@ To create the minified version, use UglifyJS like this:
|
|||
uglifyjs -c speedtest_worker.js > speedtest_worker.min.js
|
||||
```
|
||||
|
||||
Pull requests are very appreciated. If you don't use github (or git), simply contact me at [dosse91@paranoici.org](mailto:dosse91@paranoici.org).
|
||||
Pull requests are very appreciated. If you don't use github (or git), simply contact me at [info@fdossena.com](mailto:info@fdossena.com).
|
||||
|
||||
__Important:__ please add your name to modified versions to distinguish them from the main project.
|
||||
|
||||
|
@ -417,4 +428,4 @@ This software is under the GNU LGPL license, Version 3 or newer.
|
|||
To put it short: you are free to use, study, modify, and redistribute this software and modified versions of it, for free or for money.
|
||||
You can also use it in proprietary software but all changes to this software must remain under the same GNU LGPL license.
|
||||
|
||||
Contact me at [dosse91@paranoici.org](mailto:dosse91@paranoici.org) for other licensing models.
|
||||
Contact me at [info@fdossena.com](mailto:info@fdossena.com) for other licensing models.
|
||||
|
|
120
getIP.php
120
getIP.php
|
@ -1,17 +1,29 @@
|
|||
<?php
|
||||
$ip="";
|
||||
header('Content-Type: text/plain; charset=utf-8');
|
||||
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
|
||||
$ip=$_SERVER['HTTP_CLIENT_IP'];
|
||||
} elseif (!empty($_SERVER['X-Real-IP'])) {
|
||||
$ip=$_SERVER['X-Real-IP'];
|
||||
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
||||
$ip=$_SERVER['HTTP_X_FORWARDED_FOR'];
|
||||
} else {
|
||||
$ip=$_SERVER['REMOTE_ADDR'];
|
||||
}
|
||||
$ip=preg_replace("/^::ffff:/", "", $ip);
|
||||
/**
|
||||
|
||||
$ip = "";
|
||||
header('Content-Type: text/plain; charset=utf-8');
|
||||
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
|
||||
$ip = $_SERVER['HTTP_CLIENT_IP'];
|
||||
} elseif (!empty($_SERVER['X-Real-IP'])) {
|
||||
$ip = $_SERVER['X-Real-IP'];
|
||||
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
||||
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
|
||||
} else {
|
||||
$ip = $_SERVER['REMOTE_ADDR'];
|
||||
}
|
||||
|
||||
$ip = preg_replace("/^::ffff:/", "", $ip);
|
||||
|
||||
if (strpos($ip, '::1') !== false) {
|
||||
echo $ip . " - localhost ipv6 access";
|
||||
die();
|
||||
}
|
||||
if (strpos($ip, '127.0.0') !== false) {
|
||||
echo $ip . " - localhost ipv4 access";
|
||||
die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Optimized algorithm from http://www.codexworld.com
|
||||
*
|
||||
* @param float $latitudeFrom
|
||||
|
@ -21,48 +33,62 @@
|
|||
*
|
||||
* @return float [km]
|
||||
*/
|
||||
function distance($latitudeFrom, $longitudeFrom, $latitudeTo, $longitudeTo){
|
||||
function distance($latitudeFrom, $longitudeFrom, $latitudeTo, $longitudeTo) {
|
||||
$rad = M_PI / 180;
|
||||
$theta = $longitudeFrom - $longitudeTo;
|
||||
$dist = sin($latitudeFrom * $rad) * sin($latitudeTo * $rad) + cos($latitudeFrom * $rad) * cos($latitudeTo * $rad) * cos($theta * $rad);
|
||||
return acos($dist) / $rad * 60 * 1.853;
|
||||
}
|
||||
if(isset($_GET["isp"])){
|
||||
$isp="";
|
||||
try{
|
||||
$json = file_get_contents("https://ipinfo.io/".$ip."/json");
|
||||
$details = json_decode($json,true);
|
||||
if(array_key_exists("org",$details)) $isp.=$details["org"]; else $isp.="Unknown ISP";
|
||||
if(array_key_exists("country",$details)) $isp.=", ".$details["country"];
|
||||
$clientLoc=NULL; $serverLoc=NULL;
|
||||
if(array_key_exists("loc",$details)) $clientLoc=$details["loc"];
|
||||
if(isset($_GET["distance"])){
|
||||
if($clientLoc){
|
||||
}
|
||||
|
||||
if (isset($_GET["isp"])) {
|
||||
$isp = "";
|
||||
try {
|
||||
$json = file_get_contents("https://ipinfo.io/" . $ip . "/json");
|
||||
$details = json_decode($json, true);
|
||||
if (array_key_exists("org", $details))
|
||||
$isp .= $details["org"];
|
||||
else
|
||||
$isp .= "Unknown ISP";
|
||||
if (array_key_exists("country", $details))
|
||||
$isp .= ", " . $details["country"];
|
||||
$clientLoc = NULL;
|
||||
$serverLoc = NULL;
|
||||
if (array_key_exists("loc", $details))
|
||||
$clientLoc = $details["loc"];
|
||||
if (isset($_GET["distance"])) {
|
||||
if ($clientLoc) {
|
||||
$json = file_get_contents("https://ipinfo.io/json");
|
||||
$details = json_decode($json,true);
|
||||
if(array_key_exists("loc",$details)) $serverLoc=$details["loc"];
|
||||
if($serverLoc){
|
||||
try{
|
||||
$clientLoc=explode(",",$clientLoc);
|
||||
$serverLoc=explode(",",$serverLoc);
|
||||
$dist=distance($clientLoc[0],$clientLoc[1],$serverLoc[0],$serverLoc[1]);
|
||||
if($_GET["distance"]=="mi"){
|
||||
$dist/=1.609344;
|
||||
$dist=round($dist,-1);
|
||||
if($dist<15) $dist="<15";
|
||||
$isp.=" (".$dist." mi)";
|
||||
}else if($_GET["distance"]=="km"){
|
||||
$dist=round($dist,-1);
|
||||
if($dist<20) $dist="<20";
|
||||
$isp.=" (".$dist." km)";
|
||||
$details = json_decode($json, true);
|
||||
if (array_key_exists("loc", $details))
|
||||
$serverLoc = $details["loc"];
|
||||
if ($serverLoc) {
|
||||
try {
|
||||
$clientLoc = explode(",", $clientLoc);
|
||||
$serverLoc = explode(",", $serverLoc);
|
||||
$dist = distance($clientLoc[0], $clientLoc[1], $serverLoc[0], $serverLoc[1]);
|
||||
if ($_GET["distance"] == "mi") {
|
||||
$dist /= 1.609344;
|
||||
$dist = round($dist, -1);
|
||||
if ($dist < 15)
|
||||
$dist = "<15";
|
||||
$isp .= " (" . $dist . " mi)";
|
||||
}else if ($_GET["distance"] == "km") {
|
||||
$dist = round($dist, -1);
|
||||
if ($dist < 20)
|
||||
$dist = "<20";
|
||||
$isp .= " (" . $dist . " km)";
|
||||
}
|
||||
}catch(Exception $e){}
|
||||
} catch (Exception $e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}catch(Exception $ex){
|
||||
$isp="Unknown ISP";
|
||||
}
|
||||
echo $ip." - ".$isp;
|
||||
} else echo $ip;
|
||||
} catch (Exception $ex) {
|
||||
$isp = "Unknown ISP";
|
||||
}
|
||||
echo $ip . " - " . $isp;
|
||||
} else {
|
||||
echo $ip;
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
HTML5 Speedtest v4.5.3
|
||||
HTML5 Speedtest v4.5.4
|
||||
by Federico Dossena
|
||||
https://github.com/adolfintel/speedtest/
|
||||
GNU LGPLv3 License
|
||||
|
@ -39,6 +39,7 @@ var settings = {
|
|||
xhr_multistreamDelay: 300, //how much concurrent requests should be delayed
|
||||
xhr_ignoreErrors: 1, // 0=fail on errors, 1=attempt to restart a stream if it fails, 2=ignore all errors
|
||||
xhr_dlUseBlob: false, // if set to true, it reduces ram usage but uses the hard drive (useful with large garbagePhp_chunkSize and/or high xhr_dlMultistream)
|
||||
xhr_ul_blob_megabytes: 20, //size in megabytes of the upload blobs sent in the upload test (forced to 4 on chrome mobile)
|
||||
garbagePhp_chunkSize: 20, // size of chunks sent by garbage.php (can be different if enable_quirks is active)
|
||||
enable_quirks: true, // enable quirks for specific browsers. currently it overrides settings to optimize for specific browsers, unless they are already being overridden with the start command
|
||||
ping_allowPerformanceApi: true, // if enabled, the ping test will attempt to calculate the ping more precisely using the Performance API. Currently works perfectly in Chrome, badly in Edge, and not at all in Firefox. If Performance API is not supported or the result is obviously wrong, a fallback is provided.
|
||||
|
@ -109,6 +110,10 @@ this.addEventListener('message', function (e) {
|
|||
//Edge 15 introduced a bug that causes onprogress events to not get fired, we have to use the "small chunks" workaround that reduces accuracy
|
||||
settings.forceIE11Workaround = true
|
||||
}
|
||||
if (/Chrome.(\d+)/i.test(ua)&&/Android|iPhone|iPad|iPod|Windows Phone/i.test(ua)){ //cheap af
|
||||
//Chrome mobile introduced a limitation somewhere around version 65, we have to limit XHR upload size to 4 megabytes
|
||||
settings.xhr_ul_blob_megabytes=4;
|
||||
}
|
||||
//telemetry_level has to be parsed and not just copied
|
||||
if(typeof s.telemetry_level !== 'undefined') settings.telemetry_level = s.telemetry_level === 'basic' ? 1 : s.telemetry_level === 'full' ? 2 : 0; // telemetry level
|
||||
//transform test_order to uppercase, just in case
|
||||
|
@ -252,22 +257,22 @@ function dlTest (done) {
|
|||
}.bind(this), 200)
|
||||
}
|
||||
// upload test, calls done function whent it's over
|
||||
// garbage data for upload test
|
||||
var r = new ArrayBuffer(1048576)
|
||||
try { r = new Float32Array(r); for (var i = 0; i < r.length; i++)r[i] = Math.random() } catch (e) { }
|
||||
var req = []
|
||||
var reqsmall = []
|
||||
for (var i = 0; i < 20; i++) req.push(r)
|
||||
req = new Blob(req)
|
||||
r = new ArrayBuffer(262144)
|
||||
try { r = new Float32Array(r); for (var i = 0; i < r.length; i++)r[i] = Math.random() } catch (e) { }
|
||||
reqsmall.push(r)
|
||||
reqsmall = new Blob(reqsmall)
|
||||
|
||||
var ulCalled = false // used to prevent multiple accidental calls to ulTest
|
||||
function ulTest (done) {
|
||||
tlog('ulTest')
|
||||
if (ulCalled) return; else ulCalled = true // ulTest already called?
|
||||
// garbage data for upload test
|
||||
var r = new ArrayBuffer(1048576)
|
||||
try { r = new Float32Array(r); for (var i = 0; i < r.length; i++)r[i] = Math.random() } catch (e) { }
|
||||
var req = []
|
||||
var reqsmall = []
|
||||
for (var i = 0; i < settings.xhr_ul_blob_megabytes; i++) req.push(r)
|
||||
req = new Blob(req)
|
||||
r = new ArrayBuffer(262144)
|
||||
try { r = new Float32Array(r); for (var i = 0; i < r.length; i++)r[i] = Math.random() } catch (e) { }
|
||||
reqsmall.push(r)
|
||||
reqsmall = new Blob(reqsmall)
|
||||
var totLoaded = 0.0, // total number of transmitted bytes
|
||||
startT = new Date().getTime(), // timestamp when test was started
|
||||
graceTimeDone = false, //set to true after the grace time is past
|
||||
|
|
2
speedtest_worker.min.js
vendored
2
speedtest_worker.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -49,4 +49,25 @@ if($db_type=="mysql"){
|
|||
$stmt->execute(array($ip,$ua,$lang,$dl,$ul,$ping,$jitter,$log)) or die("3");
|
||||
$conn = null;
|
||||
}
|
||||
elseif($db_type=="csv"){
|
||||
// Prepare the csv formatted string
|
||||
date_default_timezone_set($timezone);
|
||||
$date = date('Y-m-d H:i:s');
|
||||
$str = '"' . $date . '",';
|
||||
$str .= '"' . $ip . '",';
|
||||
$str .= '"' . $ua . '",';
|
||||
$str .= '"' . $dl . '",';
|
||||
$str .= '"' . $ul . '",';
|
||||
$str .= '"' . $ping . '",';
|
||||
$str .= '"' . $jitter . '"' . "\n";
|
||||
|
||||
// Set header if this is a new file
|
||||
if (!file_exists($Csv_File)) {
|
||||
$header = '"date","ip","ua","download","upload","ping","jitter"' . "\n";
|
||||
file_put_contents($Csv_File, $header, FILE_APPEND);
|
||||
}
|
||||
|
||||
// Writting line to file
|
||||
file_put_contents($Csv_File, $str, FILE_APPEND);
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
$db_type="mysql"; //Type of db: "mysql", "sqlite" or "postgresql"
|
||||
$db_type="mysql"; //Type of db: "mysql", "sqlite" or "postgresql" or "csv"
|
||||
|
||||
// Sqlite3 settings
|
||||
$Sqlite_db_file = "../telemetry.sql";
|
||||
|
@ -17,4 +17,8 @@ $PostgreSql_password="PASSWORD";
|
|||
$PostgreSql_hostname="DB_HOSTNAME";
|
||||
$PostgreSql_databasename="DB_NAME";
|
||||
|
||||
// CSV settings
|
||||
$Csv_File="reports.csv";
|
||||
$timezone='UTC';
|
||||
|
||||
?>
|
||||
|
|
Loading…
Reference in a new issue