Initial version
This commit is contained in:
parent
cc103b2337
commit
6874e3a0ce
10 changed files with 1031 additions and 2 deletions
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
34
README.md
34
README.md
|
@ -1,3 +1,35 @@
|
||||||
# ip.zuim.de
|
# [ip.zuim.de](https://ip.zuim.de)
|
||||||
|
|
||||||
Shows information on connectivity of a user, by testing both IPv4 and IPv6. Also shows geoip data.
|
Shows information on connectivity of a user, by testing both IPv4 and IPv6. Also shows geoip data.
|
||||||
|
|
||||||
|
### Warning:
|
||||||
|
This code is mostly unmaintained and uses several old javascript libraries.
|
||||||
|
|
||||||
|
### Setup:
|
||||||
|
|
||||||
|
To get the geoip data, the geoip2 module for nginx is used with the following configuration:
|
||||||
|
```
|
||||||
|
geoip2 /var/lib/GeoIP/GeoLite2-City.mmdb {
|
||||||
|
auto_reload 1h;
|
||||||
|
$geoip2_data_continent_code continent code;
|
||||||
|
$geoip2_data_continent_name continent names en;
|
||||||
|
$geoip2_data_country_code country iso_code;
|
||||||
|
$geoip2_data_country_name country names en;
|
||||||
|
$geoip2_data_subdivision subdivisions 0 names en;
|
||||||
|
$geoip2_data_city_name city names en;
|
||||||
|
$geoip2_data_postal_code postal code;
|
||||||
|
$geoip2_data_location_time location time_zone;
|
||||||
|
}
|
||||||
|
|
||||||
|
geoip2 /var/lib/GeoIP/GeoLite2-ASN.mmdb {
|
||||||
|
auto_reload 1h;
|
||||||
|
$geoip2_data_asn autonomous_system_organization;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Download these files directly and add them in the main folder:
|
||||||
|
- https://ip.zuim.de/0B.zip
|
||||||
|
- https://ip.zuim.de/1MB.zip
|
||||||
|
- https://ip.zuim.de/10MB.zip
|
||||||
|
- https://ip.zuim.de/100MB.zip
|
||||||
|
- https://ip.zuim.de/img.jpg?t=1721317515702
|
||||||
|
|
10
include/advip.php
Normal file
10
include/advip.php
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<?php
|
||||||
|
$ip = str_replace("::ffff:", "", $_SERVER['REMOTE_ADDR']);
|
||||||
|
|
||||||
|
$data = array();
|
||||||
|
$data["Hostname"] = gethostbyaddr($ip);
|
||||||
|
if($data["Hostname"]===$ip)
|
||||||
|
$data["Hostname"] = "";
|
||||||
|
|
||||||
|
echo json_encode($data);
|
||||||
|
?>
|
10
include/config.php
Normal file
10
include/config.php
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<?php
|
||||||
|
$config = array(
|
||||||
|
"ipv4" => "89.58.44.51",
|
||||||
|
"ipv6" => "2a03:4000:67:e03::1",
|
||||||
|
"nameDS" => "ip.zuim.de",
|
||||||
|
"namev4" => "v4.ip.zuim.de", # only use an A record for this domain
|
||||||
|
"namev6" => "v6.ip.zuim.de", # only use an AAAA record for this domain
|
||||||
|
"app_path" => "/",
|
||||||
|
);
|
||||||
|
?>
|
52
include/ipinfo.php
Normal file
52
include/ipinfo.php
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
<?php
|
||||||
|
require_once("config.php");
|
||||||
|
|
||||||
|
$ip = array();
|
||||||
|
|
||||||
|
$ip["host"] = rtrim($_SERVER['HTTP_HOST'], '.');
|
||||||
|
$ip["ip"] = str_replace("::ffff:", "", $_SERVER['REMOTE_ADDR']);
|
||||||
|
$ip["proxyIp"] = isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : "";
|
||||||
|
//$ip["clientIp"] = isset($_SERVER['HTTP_CLIENT_IP']) ? $_SERVER['HTTP_CLIENT_IP'] : "";
|
||||||
|
|
||||||
|
switch($ip["host"])
|
||||||
|
{
|
||||||
|
case $config["namev4"]:
|
||||||
|
case $config["ipv4"]:
|
||||||
|
$ip["name"] = "IPv4";
|
||||||
|
$ip["conHostType"] = 0;
|
||||||
|
break;
|
||||||
|
case $config["nameDS"]:
|
||||||
|
$ip["name"] = "Dualstack";
|
||||||
|
$ip["conHostType"] = 1;
|
||||||
|
break;
|
||||||
|
case $config["namev6"]:
|
||||||
|
case "[".$config["ipv6"]."]":
|
||||||
|
$ip["name"] = "IPv6";
|
||||||
|
$ip["conHostType"] = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$ip["name"] = "unknown";
|
||||||
|
$ip["conHostType"] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strpos($ip["ip"],".") !== FALSE){
|
||||||
|
$ip["conClientType"] = 0;
|
||||||
|
}
|
||||||
|
else if(strpos($ip["ip"],":") !== FALSE){
|
||||||
|
$ip["conClientType"] = 2;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
$ip["conClientType"] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ip["geoIp"] = array();
|
||||||
|
$ip["geoIp"]["Land"] = $_SERVER["GEOIP_COUNTRY_NAME"];
|
||||||
|
$ip["geoIp"]["Bundesland"] = $_SERVER["GEOIP_SUBDIVISION"];
|
||||||
|
$ip["geoIp"]["Stadt"] = $_SERVER["GEOIP_CITY_NAME"];
|
||||||
|
$ip["geoIp"]["PLZ"] = $_SERVER["GEOIP_POSTAL_CODE"];
|
||||||
|
$ip["geoIp"]["ISP"] = $_SERVER["GEOIP_ASN"];
|
||||||
|
|
||||||
|
if(!isset($NO_JSON_OUT)) {
|
||||||
|
echo json_encode($ip);
|
||||||
|
}
|
||||||
|
?>
|
135
index.php
Executable file
135
index.php
Executable file
|
@ -0,0 +1,135 @@
|
||||||
|
<?php
|
||||||
|
$NO_JSON_OUT = 1; //include mode for ipinfo.php
|
||||||
|
|
||||||
|
require_once("include/config.php");
|
||||||
|
require_once("include/ipinfo.php");
|
||||||
|
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Netzwerktest (<?php echo $ip["name"]; ?>)</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
|
||||||
|
<link rel="manifest" href="/site.webmanifest">
|
||||||
|
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5">
|
||||||
|
<meta name="msapplication-TileColor" content="#e0e8ff">
|
||||||
|
<meta name="theme-color" content="#b7eeff">
|
||||||
|
<link rel="stylesheet" type="text/css" href="style.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="cont">
|
||||||
|
|
||||||
|
<h1><a class="title" href="//<?php echo $ip["host"].$config["app_path"]; ?>">
|
||||||
|
<?php echo $ip["name"]; ?> - Testseite
|
||||||
|
</a></h1>
|
||||||
|
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<div class="ipTest">
|
||||||
|
<div class="ip_v4"><div class="info_ip">Warte auf IPv4 <div class="lds-ellipsis"><div></div><div></div><div></div><div></div></div></div><div class="info_geo"></div></div>
|
||||||
|
<hr style="margin-top:0;margin-bottom:0;">
|
||||||
|
<div class="ip_v6"><div class="info_ip">Warte auf IPv6 <div class="lds-ellipsis"><div></div><div></div><div></div><div></div></div></div><div class="info_geo"></div></div>
|
||||||
|
<div class="ip_ds" style="display:none;"><div class="info_ip"></div><div class="info_geo"></div></div>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<h3>Informationen & Downloads</h3>
|
||||||
|
<div id="resultExplanation"></div>
|
||||||
|
<?php
|
||||||
|
if($ip["conHostType"] == 1)
|
||||||
|
{
|
||||||
|
if($ip["conClientType"]==0)
|
||||||
|
{
|
||||||
|
echo "Dein Browser hat <b>IPv4</b> ausgewählt, um sich zu verbinden!<br>";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
echo "Dein Browser hat <b>IPv6</b> ausgewählt, um sich zu verbinden!<br>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
echo "Wenn diese Seite angezeigt wird unterstützt der Client <b>".$ip["name"]."</b>!<br>";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isset($_SERVER['HTTPS']) && "on" == $_SERVER['HTTPS'])
|
||||||
|
{
|
||||||
|
echo "Du bist mit <b>https</b> verbunden.";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
echo "Du bist mit <b>http</b> verbunden.";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<p>Download mit <?php echo $ip["name"]; ?>:
|
||||||
|
<a href="1MB.zip">1MB Download</a>,
|
||||||
|
<a href="10MB.zip">10MB Download</a>,
|
||||||
|
<a href="100MB.zip">100MB Download</a></p>
|
||||||
|
|
||||||
|
<p>Weitere Informationen:
|
||||||
|
<a href="//<?php echo $config["nameDS"]; ?>/raw/" target="_blank">Nur IP Adresse als Text</a>,
|
||||||
|
<a href="//status.zuim.de/" target="_blank">Server Statusseite</a>,
|
||||||
|
<a href="//zuim.de/" target="_blank">zuim.de Hauptseite </a></p>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h3 class='headCont'>
|
||||||
|
Rufe diese Seite direkt über
|
||||||
|
<a href="https://<?php echo $config["namev4"] . $config["app_path"]; ?>"> IPV4</a>
|
||||||
|
<a href="http://<?php echo $config["ipv4"] . $config["app_path"]; ?>" class="secondary_link">(Ohne DNS)</a>
|
||||||
|
<a href="https://<?php echo $config["nameDS"] . $config["app_path"]; ?>">Dualstack</a>
|
||||||
|
<a href="http://<?php echo $config["namev6"] . $config["app_path"]; ?>"> IPV6</a>
|
||||||
|
<a href="http://[<?php echo $config["ipv6"]."]" . $config["app_path"]; ?>" class="secondary_link">(Ohne DNS)</a>
|
||||||
|
auf.</h3>
|
||||||
|
<noscript>Aktiviere Javascript, für mehr Informationen:<br>IP: <?php echo $ip["ip"]; ?></noscript>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h3>Ping mit Graph messen: <button class="start">Start</button></h3>
|
||||||
|
|
||||||
|
<div class="out"></div>
|
||||||
|
<div class="ct-chart ct-octave" style="display: none;"></div>
|
||||||
|
<hr>
|
||||||
|
<h3>Andere Tests für Geschwindigkeit & Ping:</h3>
|
||||||
|
<a href="//craftandbuild.de/speedtest/speedtest_ajax">Speedtest mit ajax</a>
|
||||||
|
<a href="//craftandbuild.de/speedtest/speedtest_websocket">Speedtest mit websocket</a>
|
||||||
|
<a href="//craftandbuild.de/WebSockets/Pingtest">Pingtest mit websocket</a>
|
||||||
|
<a href="/librespeed/">LibreSpeed Instanz</a>
|
||||||
|
<button class="ping"><?php echo $ip["name"]; ?> Ping</button><br><span class="pingresult"></span>
|
||||||
|
<hr>
|
||||||
|
<h3>Bild(14MB) parallel mit IPv4 und IPv6 laden: <button class="speed">Start</button></h3>
|
||||||
|
<div class="images">
|
||||||
|
<div class="v4">
|
||||||
|
<h3>IPv4</h3>
|
||||||
|
<img class="testimg" src="" alt="v4 Test"/>
|
||||||
|
<p></p>
|
||||||
|
</div>
|
||||||
|
<div class="v6">
|
||||||
|
<h3>IPv6</h3>
|
||||||
|
<img class="testimg" src="" alt="v6 Test"/>
|
||||||
|
<p></p>
|
||||||
|
</div>
|
||||||
|
<br style="clear:both;">
|
||||||
|
<h3 class="ausg"></h3>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- libs -->
|
||||||
|
<script src="//cdn.zuim.de/js/jQuery/jquery.js"></script>
|
||||||
|
<script defer src="//cdn.zuim.de/js/socket.io-4.1.2.js"></script>
|
||||||
|
<script defer src="//cdn.zuim.de/js/chartist-js-0.11.4/chartist.min.js"></script>
|
||||||
|
<script defer src="//cdn.zuim.de/js/chartist-js-0.11.4/chartist-plugin-axistitle.min.js"></script>
|
||||||
|
<script defer src="//cdn.zuim.de/js/chartist-js-0.11.4/chartist-plugin-legend.js"></script>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="//cdn.zuim.de/css/chartist.min.css">
|
||||||
|
<!-- scripts -->
|
||||||
|
<script>
|
||||||
|
var config = <?php echo json_encode($config); ?>;
|
||||||
|
var ipInfo_php = <?php echo json_encode($ip); ?>;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script src="script.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
3
raw/index.php
Executable file
3
raw/index.php
Executable file
|
@ -0,0 +1,3 @@
|
||||||
|
<?php
|
||||||
|
echo str_replace("::ffff:", "", $_SERVER['REMOTE_ADDR'])."\n";
|
||||||
|
?>
|
7
robots.txt
Normal file
7
robots.txt
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
User-agent: *
|
||||||
|
Disallow: 100KB.zip
|
||||||
|
Disallow: 500KB.zip
|
||||||
|
Disallow: 1MB.zip
|
||||||
|
Disallow: 10MB.zip
|
||||||
|
Disallow: 100MB.zip
|
||||||
|
Disallow: 1GB.zip
|
509
script.js
Normal file
509
script.js
Normal file
|
@ -0,0 +1,509 @@
|
||||||
|
function copyBtn(className, btn){
|
||||||
|
var ele = $("."+className);
|
||||||
|
highlight(ele[0]);
|
||||||
|
document.execCommand('copy');
|
||||||
|
$(btn).css("backgroundColor","#0c0").delay(500).queue(function() {
|
||||||
|
$(btn).css("backgroundColor","");
|
||||||
|
$(btn).dequeue();
|
||||||
|
});
|
||||||
|
console.log("copied: "+ele.html());
|
||||||
|
}
|
||||||
|
function highlight(ele){
|
||||||
|
var range, selection;
|
||||||
|
if (document.body.createTextRange)
|
||||||
|
{
|
||||||
|
range = document.body.createTextRange();
|
||||||
|
range.moveToElementText(ele);
|
||||||
|
range.select();
|
||||||
|
} else if (window.getSelection)
|
||||||
|
{
|
||||||
|
selection = window.getSelection();
|
||||||
|
range = document.createRange();
|
||||||
|
range.selectNodeContents(ele);
|
||||||
|
selection.removeAllRanges();
|
||||||
|
selection.addRange(range);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$(document).ready(function()
|
||||||
|
{
|
||||||
|
var v4Div = $(".ip_v4");
|
||||||
|
var v6Div = $(".ip_v6");
|
||||||
|
var dsDiv = $(".ip_ds");
|
||||||
|
|
||||||
|
var testingResult = {};
|
||||||
|
|
||||||
|
function getIpInfo(url, div)
|
||||||
|
{
|
||||||
|
var infoDivIp = div.children(".info_ip");
|
||||||
|
var infoDivGeo = div.children(".info_geo");
|
||||||
|
var version = url.includes("4")?4:6
|
||||||
|
|
||||||
|
infoDivGeo.hide();
|
||||||
|
|
||||||
|
|
||||||
|
function getIpInfoDone(data) {
|
||||||
|
var className = "ip_"+url.replace(/\./g,"");
|
||||||
|
testingResult[version] = true;
|
||||||
|
if(testingResult[4] && testingResult[6]) {
|
||||||
|
$("#resultExplanation").html("Die Verbindung konnte über IPv4 und IPv6 hergestellt werden, also wird Dual-Stack unterstützt! Dies kann nativ, durch DS-Lite oder einen 6to4/4to6 Tunnel umgesetzt sein.<br><br>");
|
||||||
|
}
|
||||||
|
|
||||||
|
div.addClass("success");
|
||||||
|
infoDivIp.html("<h3>Deine <a href='//"+data.host+"/raw/'>"+data.name+" Adresse</a>: "+
|
||||||
|
"<span class='"+className+" ipAddr' onclick='highlight(this)'>"+data.ip+" </span> "+
|
||||||
|
"<button style='vertical-align: middle' onclick='copyBtn(\""+className+"\", this)'>Kopieren</button></h3>");
|
||||||
|
if(data.proxyIp != ""){
|
||||||
|
infoDivIp.append("<p>Vom Proxy angegebene Ip: "+data.proxyIp+" (HTTP_X_FORWARDED_FOR)</p>");
|
||||||
|
}
|
||||||
|
//if(data.clientIp != ""){
|
||||||
|
// infoDivIp.append("<p>Vom Client angegebene Ip: "+data.clientIp+" (HTTP_CLIENT_IP)</p>");
|
||||||
|
//}
|
||||||
|
|
||||||
|
for(var ele in data.geoIp)
|
||||||
|
{
|
||||||
|
if(data.geoIp[ele] != ""){
|
||||||
|
infoDivGeo.append("<span class='info'>"+ele+":</span>"+data.geoIp[ele]+"<br>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
infoDivGeo.fadeIn();
|
||||||
|
|
||||||
|
//start hostname request
|
||||||
|
$.ajax("//"+url+"/include/advip.php", {dataType: "json", timeout: 5000})
|
||||||
|
.done(function(data, status, xhr){
|
||||||
|
for(var ele in data)
|
||||||
|
{
|
||||||
|
if(data[ele] != ""){
|
||||||
|
infoDivGeo.prepend("<span class='info'>"+ele+":</span>"+data[ele]+"<br>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}).fail(function(){
|
||||||
|
//fail geoip silently
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(ipInfo_php.conHostType==(div==v4Div?0:(div==v6Div?2:1))) {
|
||||||
|
console.log("Loaded over PHP: "+ipInfo_php.name);
|
||||||
|
getIpInfoDone(ipInfo_php);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$.ajax("//"+url+"/include/ipinfo.php", {dataType: "json", timeout: 5000})
|
||||||
|
.done(function(data, status, xhr){
|
||||||
|
console.log("Loaded over Ajax: "+data.name);
|
||||||
|
getIpInfoDone(data);
|
||||||
|
}).fail(function(err){
|
||||||
|
testingResult[className] = false;
|
||||||
|
console.log(err);
|
||||||
|
div.addClass("failure");
|
||||||
|
infoDivIp.html("<span style='font-weight: bold;'>IPv"+version+" nicht verfügbar.</span>");
|
||||||
|
|
||||||
|
var ipWithoutDNS;
|
||||||
|
var name;
|
||||||
|
if(version == 4){
|
||||||
|
ipWithoutDNS = config["ipv4"];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ipWithoutDNS = "["+config["ipv6"]+"]";
|
||||||
|
}
|
||||||
|
infoDivIp.append("<br>Versuche eine IPv"+version+" Adresse direkt aufzurufen, um auf DNS Fehler zu prüfen:"+
|
||||||
|
"<a href='http://"+ipWithoutDNS+"/'>"+ipWithoutDNS+"</a>");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getIpInfo(config.namev4, v4Div);
|
||||||
|
getIpInfo(config.namev6, v6Div);
|
||||||
|
//getIpInfo(config.nameDS, dsDiv);
|
||||||
|
|
||||||
|
var pingduration;
|
||||||
|
var pingcount;
|
||||||
|
var pingmax = 3000;
|
||||||
|
var pingInterval;
|
||||||
|
|
||||||
|
$(".ping").click(function()
|
||||||
|
{
|
||||||
|
$(".ping").prop('disabled', true);
|
||||||
|
|
||||||
|
pingduration = 0;
|
||||||
|
pingcount = 0;
|
||||||
|
|
||||||
|
ping();
|
||||||
|
|
||||||
|
setTimeout(function()
|
||||||
|
{
|
||||||
|
if(pingcount != -1)
|
||||||
|
{
|
||||||
|
$(".pingresult").html("Keine Antwort nach 5 Sekunden!");
|
||||||
|
}
|
||||||
|
|
||||||
|
$(".ping").prop('disabled', false);
|
||||||
|
},5000);
|
||||||
|
});
|
||||||
|
|
||||||
|
function ping()
|
||||||
|
{
|
||||||
|
var startTime = new Date().getTime();
|
||||||
|
var req = new XMLHttpRequest();
|
||||||
|
/*
|
||||||
|
0 UNSENT open()wurde noch nicht aufgerufen.
|
||||||
|
1 OPENED send()wurde noch nicht aufgerufen.
|
||||||
|
2 HEADERS_RECEIVED send() wurde aufgerufen, und Headers sowie Status sind verfügbar.
|
||||||
|
3 LOADING Download ist im Gange; responseText enthält bereits unvollständige Daten.
|
||||||
|
4 DONE Der Vorgang ist abgeschlossen.*/
|
||||||
|
req.onreadystatechange = function()
|
||||||
|
{
|
||||||
|
|
||||||
|
//console.log(req.readyState+" "+(new Date().getTime() - startTime));
|
||||||
|
if(req.readyState == 2 && pingcount >= 0)
|
||||||
|
{
|
||||||
|
var duration = new Date().getTime() - startTime;
|
||||||
|
|
||||||
|
pingduration += duration;
|
||||||
|
pingcount++;
|
||||||
|
|
||||||
|
$(".pingresult").html("Anzahl der Pings: "+pingcount+"<br>Zeit: "+Math.round(pingduration/pingcount * 10)/10 + "ms");
|
||||||
|
|
||||||
|
if(pingduration > pingmax)
|
||||||
|
{
|
||||||
|
$(".pingresult").append("<br>Fertig!");
|
||||||
|
pingcount = -1;
|
||||||
|
clearInterval(pingInterval);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ping();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
req.open("GET", "/0B.zip?"+startTime);
|
||||||
|
req.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
$(".speed").click(function()
|
||||||
|
{
|
||||||
|
var v4 = -1;
|
||||||
|
var v6 = -1;
|
||||||
|
var v4Speed = -1;
|
||||||
|
var v6Speed = -1;
|
||||||
|
var timeCount = 15;
|
||||||
|
|
||||||
|
$(this).hide();
|
||||||
|
$(".images").show();
|
||||||
|
time = new Date().getTime();
|
||||||
|
$(".v4 img").attr("src","//"+config.namev4+"/img.jpg?t="+time);
|
||||||
|
$(".v6 img").attr("src","//"+config.namev6+"/img.jpg?t="+time);
|
||||||
|
$(".v4 img, .v6 img").on("load", function()
|
||||||
|
{
|
||||||
|
dauer = (new Date().getTime()-time)/1000;
|
||||||
|
speed = Math.round((14*8)/dauer*100)/100;
|
||||||
|
|
||||||
|
$(this).next().html(speed + " Mbit/s für "+dauer + " Sekunden ");
|
||||||
|
|
||||||
|
//wert setzen
|
||||||
|
if($(this).parent().hasClass("v4"))
|
||||||
|
{
|
||||||
|
v4 = dauer;
|
||||||
|
v4Speed = speed;
|
||||||
|
}
|
||||||
|
if($(this).parent().hasClass("v6"))
|
||||||
|
{
|
||||||
|
v6 = dauer;
|
||||||
|
v6Speed = speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
//fertig
|
||||||
|
fertig();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var intervall = setInterval(function(){timer()},100);
|
||||||
|
|
||||||
|
function timer()
|
||||||
|
{
|
||||||
|
//count
|
||||||
|
timeCount = (timeCount*10-1)/10;
|
||||||
|
|
||||||
|
//ausgabe
|
||||||
|
$(".ausg").html("Timeout: "+timeCount);
|
||||||
|
|
||||||
|
fertig();
|
||||||
|
}
|
||||||
|
|
||||||
|
function fertig()
|
||||||
|
{
|
||||||
|
if(timeCount <= 0 || v4 != -1 && v6 != -1)
|
||||||
|
{
|
||||||
|
clearInterval(intervall);
|
||||||
|
ausg = "";
|
||||||
|
win = -1;
|
||||||
|
loose = -1;
|
||||||
|
if(v4 == -1 && v6 == -1)
|
||||||
|
{
|
||||||
|
ausg = "Beide haben das laden nach Beenden des Timeout nicht abgeschlossen!";
|
||||||
|
win = 0;
|
||||||
|
loose = 0;
|
||||||
|
}
|
||||||
|
else if(v4 == -1)
|
||||||
|
{
|
||||||
|
ausg = "Nur IPv6 hat mit "+v6+" Sekunden funktioniert!";
|
||||||
|
win = 6;
|
||||||
|
loose = 4;
|
||||||
|
}
|
||||||
|
else if(v6 == -1)
|
||||||
|
{
|
||||||
|
ausg = "Nur IPv4 hat mit "+v4+" Sekunden funktioniert!";
|
||||||
|
win = 4;
|
||||||
|
loose = 6;
|
||||||
|
}
|
||||||
|
else if(v4 < v6)
|
||||||
|
{
|
||||||
|
ausg = "IPv4 war " + Math.round((v6/v4)*100)/100 + " mal schneller als IPv6";
|
||||||
|
win = 4;
|
||||||
|
loose = 6;
|
||||||
|
}
|
||||||
|
else if(v6 <= v4)
|
||||||
|
{
|
||||||
|
ausg = "IPv6 war " + Math.round((v4/v6)*100)/100 + " mal schneller als IPv4";
|
||||||
|
win = 6;
|
||||||
|
loose = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
$(".ausg").html("<h3>"+ausg+" <button onClick='location.reload();'> Seite erneut laden </button></h3>");
|
||||||
|
|
||||||
|
$(".v"+win).css("border", "5px solid #0a0");
|
||||||
|
$(".v"+loose).css("border", "5px solid #a00");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var active = false;
|
||||||
|
|
||||||
|
var id = -1; //ignore first measurement
|
||||||
|
var times4 = [];
|
||||||
|
var times6 = [];
|
||||||
|
var labels = [];
|
||||||
|
|
||||||
|
var startT;
|
||||||
|
|
||||||
|
$(".start").click(function() {
|
||||||
|
active = !active;
|
||||||
|
|
||||||
|
if(active) {
|
||||||
|
$(".start").html("Stop");
|
||||||
|
loadChart();
|
||||||
|
|
||||||
|
s4 = io('wss://'+config.namev4+'/', {path: '/speedtest'});
|
||||||
|
s6 = io('wss://'+config.namev6+'/', {path: '/speedtest'});
|
||||||
|
|
||||||
|
s4.on('pongDown', function(msg) {
|
||||||
|
times4[msg] = new Date().getTime() - times4[msg];
|
||||||
|
//console.log("Received via v4: " + msg + " Time:" + times4[msg]);
|
||||||
|
updateChart(msg, false);
|
||||||
|
});
|
||||||
|
s6.on('pongDown', function(msg) {
|
||||||
|
times6[msg] = new Date().getTime() - times6[msg];
|
||||||
|
//console.log("Received via v6: " + msg + " Time:" + times6[msg]);
|
||||||
|
updateChart(msg, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
$(".out").html("Starte websocket<br>Wenn dies nicht funktioniert ist der NodeJS Server offline!");
|
||||||
|
$(".ct-chart").show();
|
||||||
|
$("html, body").scrollTop($(".ct-chart").offset().top);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
times4 = [];
|
||||||
|
times6 = [];
|
||||||
|
labels = [];
|
||||||
|
nTimes4 = [];
|
||||||
|
nTimes6 = [];
|
||||||
|
nLabels = [];
|
||||||
|
$(".start").html("Start");
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
setInterval(function() {
|
||||||
|
if(active) {
|
||||||
|
|
||||||
|
if(id >= 0) {
|
||||||
|
times4[id] = new Date().getTime();
|
||||||
|
times6[id] = new Date().getTime();
|
||||||
|
labels[id] = ""+(id/5);
|
||||||
|
}
|
||||||
|
s4.emit('pingUp', id);
|
||||||
|
s6.emit('pingUp', id);
|
||||||
|
|
||||||
|
id++;
|
||||||
|
}
|
||||||
|
}, 200);
|
||||||
|
|
||||||
|
function calcAvg()
|
||||||
|
{
|
||||||
|
var n4 = 0;
|
||||||
|
var avgAct4 = 0;
|
||||||
|
for(var i = 0; i < nTimes4.length; i++)
|
||||||
|
{
|
||||||
|
if(nTimes4[i]) {
|
||||||
|
avgAct4 += nTimes4[i];
|
||||||
|
n4++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
avgAct4 /= n4;
|
||||||
|
|
||||||
|
|
||||||
|
var n6 = 0;
|
||||||
|
var avgAct6 = 0;
|
||||||
|
for(var i = 0; i < nTimes6.length; i++)
|
||||||
|
{
|
||||||
|
if(nTimes6[i]) {
|
||||||
|
avgAct6 += nTimes6[i];
|
||||||
|
n6++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
avgAct6 /= n6;
|
||||||
|
|
||||||
|
$(".out").html("Ping Durchschnitt: IPv4: "+avgAct4.toFixed(1)+" ms / IPv6: "+avgAct6.toFixed(1)+" ms (Anfragen: "+n4+")");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var nTimes4 = [];
|
||||||
|
var nTimes6 = [];
|
||||||
|
var nLabels = [];
|
||||||
|
var chart;
|
||||||
|
function loadChart()
|
||||||
|
{
|
||||||
|
//trim data
|
||||||
|
/*var n = 50;
|
||||||
|
var start = 0>times4.length-n?0:times4.length-n;
|
||||||
|
|
||||||
|
for(var i = start; i < times4.length; i++)
|
||||||
|
{
|
||||||
|
if(times4[i] > 100*1000)
|
||||||
|
break;
|
||||||
|
|
||||||
|
nTimes4[i-start] = times4[i];
|
||||||
|
nLabels[i-start] = labels[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
var n = 50;
|
||||||
|
var start = 0>times6.length-n?0:times6.length-n;
|
||||||
|
|
||||||
|
for(var i = start; i < times6.length; i++)
|
||||||
|
{
|
||||||
|
if(times6[i] > 100*1000)
|
||||||
|
break;
|
||||||
|
|
||||||
|
nTimes6[i-start] = times6[i];
|
||||||
|
nLabels[i-start] = labels[i];
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
calcAvg(nTimes4);
|
||||||
|
calcAvg(nTimes6);
|
||||||
|
|
||||||
|
//draw chart
|
||||||
|
var options =
|
||||||
|
{
|
||||||
|
low: 0,
|
||||||
|
|
||||||
|
axisX:
|
||||||
|
{
|
||||||
|
labelInterpolationFnc: function skipLabels(value, index)
|
||||||
|
{
|
||||||
|
return index % 10 === 0 ? value : null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
chartPadding:
|
||||||
|
{
|
||||||
|
top: 50,
|
||||||
|
right: 5,
|
||||||
|
bottom: 20,
|
||||||
|
left: 25
|
||||||
|
},
|
||||||
|
|
||||||
|
plugins: [
|
||||||
|
Chartist.plugins.legend({
|
||||||
|
clickable: false,
|
||||||
|
legendNames: ['IPv4 Ping', 'IPv6 Ping']
|
||||||
|
}),
|
||||||
|
Chartist.plugins.ctAxisTitle(
|
||||||
|
{
|
||||||
|
axisX: {
|
||||||
|
axisTitle: 'Zeit in Sekunden',
|
||||||
|
axisClass: 'ct-axis-title',
|
||||||
|
offset: {
|
||||||
|
x: 0,
|
||||||
|
y: 35
|
||||||
|
},
|
||||||
|
textAnchor: 'middle'
|
||||||
|
},
|
||||||
|
axisY: {
|
||||||
|
axisTitle: 'Ping in ms',
|
||||||
|
axisClass: 'ct-axis-title',
|
||||||
|
offset: {
|
||||||
|
x: 0,
|
||||||
|
y: -10
|
||||||
|
},
|
||||||
|
textAnchor: 'middle',
|
||||||
|
flipTitle: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
chart = new Chartist.Line('.ct-chart', {labels: nLabels, series: [nTimes4,nTimes6]}, options);
|
||||||
|
console.log(chart);
|
||||||
|
}
|
||||||
|
|
||||||
|
var idToIndex = [];
|
||||||
|
function updateChart(id, v6) {
|
||||||
|
if(id < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var limit = 50;
|
||||||
|
|
||||||
|
if(nLabels.length >= limit) {
|
||||||
|
nLabels.shift();
|
||||||
|
}
|
||||||
|
if(nTimes4.length >= limit) {
|
||||||
|
nTimes4.shift();
|
||||||
|
}
|
||||||
|
if(nTimes6.length >= limit) {
|
||||||
|
nTimes6.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!nLabels.includes(labels[id])) {
|
||||||
|
nLabels.push(labels[id]);
|
||||||
|
|
||||||
|
//set other value to null while waiting
|
||||||
|
if(v6) {
|
||||||
|
nTimes6.push(times6[id]);
|
||||||
|
nTimes4.push(null);
|
||||||
|
} else {
|
||||||
|
nTimes4.push(times4[id]);
|
||||||
|
nTimes6.push(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
//replace previously inserted null value
|
||||||
|
if(v6) {
|
||||||
|
nTimes6[nTimes6.length-1] = times6[id];
|
||||||
|
} else {
|
||||||
|
nTimes4[nTimes4.length-1] = times4[id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
calcAvg(nTimes4);
|
||||||
|
calcAvg(nTimes6);
|
||||||
|
|
||||||
|
chart.update({labels: nLabels, series: [nTimes4,nTimes6]});
|
||||||
|
}
|
||||||
|
});
|
265
style.css
Normal file
265
style.css
Normal file
|
@ -0,0 +1,265 @@
|
||||||
|
*
|
||||||
|
{
|
||||||
|
font-family: Arial;
|
||||||
|
}
|
||||||
|
h4,h3,h5,h6
|
||||||
|
{
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
|
.v4, .v6
|
||||||
|
{
|
||||||
|
float:left;
|
||||||
|
width: 45%;
|
||||||
|
border: 3px solid black;
|
||||||
|
border-radius:10px;
|
||||||
|
margin: 5px;
|
||||||
|
padding: 0;
|
||||||
|
overflow:hidden;
|
||||||
|
}
|
||||||
|
.v4 p, .v4 h3, .v6 p, .v6 h3
|
||||||
|
{
|
||||||
|
margin: 0 5px;
|
||||||
|
}
|
||||||
|
.images
|
||||||
|
{
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
.testimg
|
||||||
|
{
|
||||||
|
height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
html,body
|
||||||
|
{
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background-color: #1e1e1e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Hauptcontainer*/
|
||||||
|
.cont
|
||||||
|
{
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right:0;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 1000px;
|
||||||
|
min-height: 100%;
|
||||||
|
margin: -10px auto -10px auto;
|
||||||
|
background: #f0f0f0;
|
||||||
|
border: 1px solid #999;
|
||||||
|
border-width: 0 1px;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: visible;
|
||||||
|
padding: 10px 10px 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
.cont h1
|
||||||
|
{
|
||||||
|
background: #4B87E7;
|
||||||
|
width: 200%;
|
||||||
|
margin-left: -10px;
|
||||||
|
padding: 10px;
|
||||||
|
color: #e7e7e7;
|
||||||
|
}
|
||||||
|
.headCont
|
||||||
|
{
|
||||||
|
padding: unset;
|
||||||
|
}
|
||||||
|
.headCont a
|
||||||
|
{
|
||||||
|
margin:3px;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
hr
|
||||||
|
{
|
||||||
|
width: 200%;
|
||||||
|
margin: 10px 0 10px -30px;
|
||||||
|
height: 3px;
|
||||||
|
background: rgba(0,0,0,0.4);
|
||||||
|
border: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
span.info
|
||||||
|
{
|
||||||
|
display:inline-block;
|
||||||
|
font-weight:bold;
|
||||||
|
width:105px;
|
||||||
|
}
|
||||||
|
a
|
||||||
|
{
|
||||||
|
text-decoration: none;
|
||||||
|
color: #4B87E7;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 0 2px;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
a.title
|
||||||
|
{
|
||||||
|
color: #eaeaea;
|
||||||
|
}
|
||||||
|
a:hover
|
||||||
|
{
|
||||||
|
background: #4B87E7;
|
||||||
|
color: #f5f5f5;
|
||||||
|
}
|
||||||
|
a.title:hover
|
||||||
|
{
|
||||||
|
color: #111;
|
||||||
|
}
|
||||||
|
.secondary_link
|
||||||
|
{
|
||||||
|
font-size:70%;
|
||||||
|
vertical-align:top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ipAddr {
|
||||||
|
font-weight:normal;
|
||||||
|
cursor:pointer;
|
||||||
|
}
|
||||||
|
.ipTest{
|
||||||
|
margin: -10px;
|
||||||
|
}
|
||||||
|
.ipTest > div{
|
||||||
|
padding: 10px;
|
||||||
|
transition: all 0.4s;
|
||||||
|
background-color: rgba(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
.ipTest .success {
|
||||||
|
background-color: rgb(220, 255, 160);
|
||||||
|
}
|
||||||
|
.ipTest .failure {
|
||||||
|
background-color: rgba(255, 100, 136, 0.46);
|
||||||
|
}
|
||||||
|
.info_geo{
|
||||||
|
transition: all 0.3s;
|
||||||
|
padding: 7px;
|
||||||
|
margin: -7px;
|
||||||
|
border-radius: 10px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.info_geo:hover{
|
||||||
|
background: rgba(255,255,255,0.8);
|
||||||
|
box-shadow: inset 0 0 10px black;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* loading icon */
|
||||||
|
.lds-ellipsis {
|
||||||
|
margin-left: 20px;
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
width: 40px;
|
||||||
|
height: 11px;
|
||||||
|
}
|
||||||
|
.lds-ellipsis div {
|
||||||
|
position: absolute;
|
||||||
|
width: 13px;
|
||||||
|
height: 13px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #fff;
|
||||||
|
animation-timing-function: cubic-bezier(0, 1, 1, 0);
|
||||||
|
box-shadow: 0 0 5px black;
|
||||||
|
}
|
||||||
|
.lds-ellipsis div:nth-child(1) {
|
||||||
|
left: 8px;
|
||||||
|
animation: lds-ellipsis1 0.6s infinite;
|
||||||
|
}
|
||||||
|
.lds-ellipsis div:nth-child(2) {
|
||||||
|
left: 8px;
|
||||||
|
animation: lds-ellipsis2 0.6s infinite;
|
||||||
|
}
|
||||||
|
.lds-ellipsis div:nth-child(3) {
|
||||||
|
left: 32px;
|
||||||
|
animation: lds-ellipsis2 0.6s infinite;
|
||||||
|
}
|
||||||
|
.lds-ellipsis div:nth-child(4) {
|
||||||
|
left: 56px;
|
||||||
|
animation: lds-ellipsis3 0.6s infinite;
|
||||||
|
}
|
||||||
|
@keyframes lds-ellipsis1 {
|
||||||
|
0% {
|
||||||
|
transform: scale(0);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes lds-ellipsis3 {
|
||||||
|
0% {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes lds-ellipsis2 {
|
||||||
|
0% {
|
||||||
|
transform: translate(0, 0);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translate(24px, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*chart*/
|
||||||
|
|
||||||
|
/*v4*/
|
||||||
|
.ct-series-a .ct-line,
|
||||||
|
.ct-legend .ct-series-0:before {
|
||||||
|
stroke: #363880 !important;
|
||||||
|
background-color: #363880 !important;
|
||||||
|
border-color: #363880 !important;
|
||||||
|
}
|
||||||
|
.ct-series-a .ct-point
|
||||||
|
{
|
||||||
|
fill: #363880 !important;
|
||||||
|
stroke: #363880 !important;
|
||||||
|
}
|
||||||
|
/*v6*/
|
||||||
|
.ct-series-b .ct-line,
|
||||||
|
.ct-legend .ct-series-1:before {
|
||||||
|
stroke: #FA9100 !important;
|
||||||
|
background-color: #FA9100 !important;
|
||||||
|
border-color: #FA9100 !important;
|
||||||
|
}
|
||||||
|
.ct-series-b .ct-point
|
||||||
|
{
|
||||||
|
fill: #FA9100 !important;
|
||||||
|
stroke: #FA9100 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*Legende*/
|
||||||
|
.ct-legend {
|
||||||
|
background: rgba(255,255,255,0.7);
|
||||||
|
padding: 3px;
|
||||||
|
border-radius: 5px;
|
||||||
|
position: absolute;
|
||||||
|
right:10px;
|
||||||
|
top: 10px;
|
||||||
|
z-index: 10;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
.ct-legend li {
|
||||||
|
position: relative;
|
||||||
|
padding-left: 23px;
|
||||||
|
margin-bottom: 3px;
|
||||||
|
}
|
||||||
|
.ct-legend li:before {
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
content: '';
|
||||||
|
border: 3px solid transparent;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
.ct-legend li.inactive:before {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
.ct-legend.ct-legend-inside {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
Loading…
Reference in a new issue