Cleanup code #17

Merged
Jeremy Kescher merged 2 commits from jeremy/0129/cleanup into master 2020-01-29 09:40:48 +00:00
3 changed files with 62 additions and 111 deletions

View file

@ -1,4 +1,4 @@
enum ServerStatus { unknown, ok, notok, timeout, dnserror, toomanyredirects } enum ServerStatus { unknown, ok, notok, timeout, dnserror }
class Server { class Server {
String displayName; String displayName;

View file

@ -11,15 +11,6 @@ import 'server.dart';
class ServerList extends StatefulWidget { class ServerList extends StatefulWidget {
ServerList({Key key, this.title}) : super(key: key); ServerList({Key key, this.title}) : super(key: key);
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title; final String title;
@override @override
@ -27,6 +18,7 @@ class ServerList extends StatefulWidget {
} }
class _ServerListState extends State<ServerList> { class _ServerListState extends State<ServerList> {
// Currently expanded server list entry, -1 = no field is expanded
int selectedServer = -1; int selectedServer = -1;
List<Server> servers = [ List<Server> servers = [
new Server( new Server(
@ -44,7 +36,7 @@ class _ServerListState extends State<ServerList> {
new Server( new Server(
"Raspberry Pi", "Raspberry Pi",
"https://pi.kescher.at/isup", "https://pi.kescher.at/isup",
) ),
]; ];
Timer timer; Timer timer;
@ -55,9 +47,8 @@ class _ServerListState extends State<ServerList> {
super.initState(); super.initState();
_updateAllServers(); _updateAllServers();
timer = new Timer.periodic(new Duration(seconds: 30), (timer) { timer = new Timer.periodic(
_updateAllServers(); new Duration(seconds: 30), (_) => _updateAllServers());
});
} }
void _updateAllServers() async { void _updateAllServers() async {
@ -65,11 +56,7 @@ class _ServerListState extends State<ServerList> {
} }
void _updateServerStatus(Server s) { void _updateServerStatus(Server s) {
_checkStatus(s.uri).then((value) { _checkStatus(s.uri).then((value) => setState(() => s.status = value));
setState(() {
s.status = value;
});
});
} }
@override @override
@ -263,7 +250,7 @@ class _ServerListState extends State<ServerList> {
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return AlertDialog( return AlertDialog(
title: Text('Are you shure you want to delete ' + title: Text('Are you sure you want to delete ' +
servers[index].displayName + servers[index].displayName +
'?'), '?'),
content: Form( content: Form(
@ -323,9 +310,7 @@ class _ServerListState extends State<ServerList> {
} }
return GestureDetector( return GestureDetector(
onTap: () { onTap: () {
setState(() { setState(() => selectedServer = index);
selectedServer = index;
});
print(index.toString() + " clicked"); print(index.toString() + " clicked");
}, },
child: Container( child: Container(
@ -368,8 +353,7 @@ class _ServerListState extends State<ServerList> {
return list; return list;
} }
static Future<ServerStatus> _checkStatus(String uri, static Future<ServerStatus> _checkStatus(String uri) async {
{int iterations = 0}) async {
Uri parsedUri; Uri parsedUri;
try { try {
@ -378,126 +362,89 @@ class _ServerListState extends State<ServerList> {
return ServerStatus.dnserror; return ServerStatus.dnserror;
} }
if (parsedUri.isScheme("http") || parsedUri.isScheme("https")) { try {
InternetAddress ia; // Check if host is IP address
InternetAddress(parsedUri.host);
} catch (ArgumentError) /* Host is a DNS name */ {
try { try {
ia = InternetAddress(parsedUri.host); var v4recs = await DnsUtils.lookupRecord(parsedUri.host, RRecordType.A);
return await _checkResponse(parsedUri, iterations); var v6recs =
} catch (ArgumentError) /* Host is a DNS name */ { await DnsUtils.lookupRecord(parsedUri.host, RRecordType.AAAA);
try { var v4 = await _resolveHostname(v4recs, RRecordType.A);
var v4recs = var v6 = await _resolveHostname(v6recs, RRecordType.AAAA);
await DnsUtils.lookupRecord(parsedUri.host, RRecordType.A); if (v4 != "" && v6 != "") {
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.dnserror;
} }
} catch (SocketException) {
return await _checkResponse(parsedUri, iterations); return ServerStatus.dnserror;
} }
} else // non-HTTP scheme }
return ServerStatus.unknown; try {
return await _checkResponse(parsedUri);
} catch (TimeoutException) {
return ServerStatus.timeout;
}
} }
Icon _generateIcon(Server server) { Icon _generateIcon(Server server) {
var icon, color;
switch (server.status) { switch (server.status) {
case ServerStatus.unknown: case ServerStatus.unknown:
return new Icon( icon = Icons.timer;
Icons.sync, color = Colors.blueGrey.shade400;
color: Colors.blueGrey.shade400,
);
break; break;
case ServerStatus.ok: case ServerStatus.ok:
return new Icon( icon = Icons.check_box;
Icons.check_box, color = Colors.green.shade400;
color: Colors.green.shade400,
);
break; break;
case ServerStatus.notok: case ServerStatus.notok:
return new Icon( icon = Icons.indeterminate_check_box;
Icons.indeterminate_check_box, color = Colors.red;
color: Colors.red,
);
break; break;
case ServerStatus.timeout: case ServerStatus.timeout:
return new Icon( icon = Icons.timer_off;
Icons.timer_off, color = Colors.yellowAccent.shade700;
color: Colors.yellowAccent.shade700,
);
break; break;
case ServerStatus.dnserror: case ServerStatus.dnserror:
return new Icon( icon = Icons.dns;
Icons.dns, color = Colors.red.shade400;
color: Colors.red.shade400,
);
break; break;
case ServerStatus.toomanyredirects: default:
return new Icon( icon = Icons.indeterminate_check_box;
Icons.subdirectory_arrow_right, color = Colors.red;
color: Colors.red.shade400,
);
break; break;
} }
return new Icon(icon, color: color);
} }
static _getDNS(List<RRecord> records, RRecordType type) { static _resolveHostname(List<RRecord> records, RRecordType type) {
String _return; String ipAddress;
if (records == null) return ServerStatus.dnserror; if (records == null) return ServerStatus.dnserror;
records.forEach((record) { records.forEach((record) {
if (record != null) { if (ipAddress != null) {
return; return;
} }
if (record == null) { if (ipAddress == null) {
// ignore: unrelated_type_equality_checks // ignore: unrelated_type_equality_checks
if (record.rType == type) { if (record.rType == type) {
_return = record.data; ipAddress = record.data;
} }
} }
}); });
if (_return == null) _return = ""; if (ipAddress == null) ipAddress = "";
return _return; return ipAddress;
} }
static Future<ServerStatus> _checkResponse(Uri uri, int iterations) async { static Future<ServerStatus> _checkResponse(Uri uri) async {
var scheme = uri.scheme; var response = await HttpUtils.getForFullResponse(uri.toString())
var port = uri.port; .timeout(new Duration(seconds: 3));
var host = uri.host;
var location = uri.path;
for (int i = 0; i < 5; i++) { if (response.statusCode > 199 && response.statusCode < 300) {
var response = await HttpUtils.getForFullResponse(scheme + "://" + host, return ServerStatus.ok;
headers: <String, String>{"Location": location}) } else {
.timeout(new Duration(seconds: 3)); return ServerStatus.notok;
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;
} }
} }

View file

@ -26,8 +26,12 @@ dependencies:
# Needed for DNS lookup # Needed for DNS lookup
basic_utils: ^2.4.8 basic_utils: ^2.4.8
# Needed for FAB menu
flutter_speed_dial: ^1.2.5 # Might be needed for FAB menu
# flutter_speed_dial: ^1.2.5
# Server list persistence
shared_preferences: ^0.5.6+1
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: