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