Implemented server check #13

Merged
Jeremy Kescher merged 1 commit from jeremy/0128/server-check-works-now into master 2020-01-28 14:05:26 +00:00
2 changed files with 131 additions and 39 deletions

View file

@ -1,9 +1,10 @@
enum ServerStatus { unknown, timeout, responding, dnserror } enum ServerStatus { unknown, ok, notok, timeout, dnserror, toomanyredirects }
class Server { class Server {
String uri;
String displayName; String displayName;
String uri;
ServerStatus status = ServerStatus.unknown; ServerStatus status = ServerStatus.unknown;
double ping;
Server( Server(
this.displayName, this.displayName,

View file

@ -5,6 +5,7 @@ import 'dart:io';
import 'package:basic_utils/basic_utils.dart'; import 'package:basic_utils/basic_utils.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_speed_dial/flutter_speed_dial.dart'; import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:http/src/response.dart';
import 'package:server_pinger/server.dart'; import 'package:server_pinger/server.dart';
import 'server.dart'; import 'server.dart';
@ -40,7 +41,7 @@ class _ServerListState extends State<ServerList> {
), ),
new Server( new Server(
"My VPS", "My VPS",
"https://vps1.kescher.at", "http://kescher.at",
), ),
new Server( new Server(
"Raspberry Pi", "Raspberry Pi",
@ -66,18 +67,13 @@ class _ServerListState extends State<ServerList> {
} }
void _updateServerStatus(Server s) { void _updateServerStatus(Server s) {
checkStatus(s.uri).then((value) { _checkStatus(s.uri).then((value) {
if (value != s.status)
setState(() { setState(() {
s.status = value; s.status = value;
}); });
}); });
} }
void _updateUI() {
setState(() {});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done // This method is rerun every time setState is called, for instance as done
@ -180,7 +176,8 @@ class _ServerListState extends State<ServerList> {
children: [ children: [
info, info,
Container( Container(
decoration: BoxDecoration(border: Border(top: BorderSide(color: Colors.grey))), decoration: BoxDecoration(
border: Border(top: BorderSide(color: Colors.grey))),
), ),
Text('Ping: 1111'), Text('Ping: 1111'),
], ],
@ -233,41 +230,135 @@ class _ServerListState extends State<ServerList> {
return list; return list;
} }
static Future<ServerStatus> checkStatus(String uri) async { static Future<ServerStatus> _checkStatus(String uri,
{int iterations = 0}) async {
Uri parsedUri; Uri parsedUri;
try { try {
parsedUri = Uri.parse(uri); parsedUri = Uri.parse(uri);
} catch (FormatException) { } catch (FormatException) {
print("The URI was invalid, returning DNS_ERROR");
return ServerStatus.dnserror; return ServerStatus.dnserror;
} }
if (parsedUri.isScheme("http") || parsedUri.isScheme("http")) {}
if (parsedUri.isScheme("http") || parsedUri.isScheme("https")) {
InternetAddress ia;
try { try {
InternetAddress ia = InternetAddress(parsedUri.host); ia = InternetAddress(parsedUri.host);
//parsedUri.scheme return await _checkResponse(parsedUri, iterations);
} catch (ArgumentError) { } catch (ArgumentError) /* Host is a DNS name */ {
List<RRecord> record = try {
await DnsUtils.lookupRecord(parsedUri.host, RRecordType.ANY); var v4recs = await DnsUtils.lookupRecord(parsedUri.host, RRecordType.A);
var v6recs =
await DnsUtils.lookupRecord(parsedUri.host, RRecordType.AAAA);
var v4 = await _getDNS(v4recs, RRecordType.A);
var v6 = await _getDNS(v6recs, RRecordType.AAAA);
if (v4 != "" && v6 != "") {
return ServerStatus.dnserror;
}
} catch (SocketException) {
return ServerStatus.dnserror;
} }
return ServerStatus.responding; return await _checkResponse(parsedUri, iterations);
}
} else // non-HTTP scheme
return ServerStatus.unknown;
} }
Icon _generateIcon(Server server) { Icon _generateIcon(Server server) {
if (server.status == ServerStatus.unknown) switch (server.status) {
case ServerStatus.unknown:
return new Icon( return new Icon(
Icons.check_box_outline_blank, Icons.sync,
color: Colors.yellow, color: Colors.blueGrey.shade400,
); );
else if (server.status == ServerStatus.responding) break;
case ServerStatus.ok:
return new Icon( return new Icon(
Icons.check_box, Icons.check_box,
color: Colors.green, color: Colors.green.shade400,
); );
else break;
case ServerStatus.notok:
return new Icon( return new Icon(
Icons.indeterminate_check_box, Icons.indeterminate_check_box,
color: Colors.red, color: Colors.red,
); );
break;
case ServerStatus.timeout:
return new Icon(
Icons.timer_off,
color: Colors.yellowAccent.shade700,
);
break;
case ServerStatus.dnserror:
return new Icon(
Icons.dns,
color: Colors.red.shade400,
);
break;
case ServerStatus.toomanyredirects:
return new Icon(
Icons.subdirectory_arrow_right,
color: Colors.red.shade400,
);
break;
}
}
static _getDNS(List<RRecord> records, RRecordType type) {
String _return;
if (records == null) return ServerStatus.dnserror;
records.forEach((record) {
if (record != null) {
return;
}
if (record == null) {
// ignore: unrelated_type_equality_checks
if (record.rType == type) {
_return = record.data;
}
}
});
if (_return == null) _return = "";
return _return;
}
static Future<ServerStatus> _checkResponse(Uri uri, int iterations) async {
var scheme = uri.scheme;
var port = uri.port;
var host = uri.host;
var location = uri.path;
for (int i = 0; i < 5; i++) {
Response response = await HttpUtils.getForFullResponse(
scheme + "://" + host,
headers: <String, String>{"Location": location})
.timeout(new Duration(seconds: 3));
if (response.statusCode > 199 && response.statusCode < 300) {
return ServerStatus.ok;
} else if (response.statusCode == HttpStatus.movedPermanently ||
response.statusCode == HttpStatus.found ||
response.statusCode == HttpStatus.temporaryRedirect ||
response.statusCode == HttpStatus.permanentRedirect) {
if (iterations < 5) return ServerStatus.toomanyredirects;
var responseLocation = response.headers["Location"];
if (responseLocation.startsWith("http://") ||
responseLocation.startsWith("https://")) {
return await _checkStatus(responseLocation,
iterations: iterations + 1);
}
location = responseLocation;
return await _checkStatus(
scheme + "://" + host + ":" + port.toString() + location,
iterations: iterations + 1);
} else {
return ServerStatus.notok;
}
}
// Too many redirects
return ServerStatus.unknown;
} }
} }