Merge pull request #3 from adolfintel/master

.
This commit is contained in:
Harry DS Alsyundawy 2018-05-05 03:32:03 +07:00 committed by GitHub
commit 432aac6505
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 163 additions and 87 deletions

1
.gitignore vendored
View file

@ -1 +1,2 @@
ugly.bat
wishlist.txt

View file

@ -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
View file

@ -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.

150
getIP.php
View file

@ -1,68 +1,94 @@
<?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);
/**
* Optimized algorithm from http://www.codexworld.com
*
* @param float $latitudeFrom
* @param float $longitudeFrom
* @param float $latitudeTo
* @param float $longitudeTo
*
* @return float [km]
*/
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){
$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)";
}
}catch(Exception $e){}
$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
* @param float $longitudeFrom
* @param float $latitudeTo
* @param float $longitudeTo
*
* @return float [km]
*/
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) {
$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)";
}
} 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;
}
?>

View file

@ -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

File diff suppressed because one or more lines are too long

View file

@ -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);
}
?>

View file

@ -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';
?>