finalize app for presentation tomorrow #35

Merged
Jeremy Kescher merged 1 commit from jeremy/0130/finalize-for-presentation into master 2020-01-30 12:25:39 +00:00
2 changed files with 110 additions and 33 deletions

View file

@ -4,7 +4,8 @@ enum ServerStatus {
notOk, notOk,
timeout, timeout,
dnsError, dnsError,
clientConnectivityIssues clientConnectivityIssues,
certificateError
} }
class Server { class Server {

View file

@ -262,6 +262,26 @@ class _ServerListState extends State<ServerList> {
), ),
), ),
), ),
IconButton(
alignment: Alignment.center,
icon: Icon(
Icons.keyboard_arrow_up,
color: Colors.blueGrey,
),
onPressed: () {
_moveServerUp(index);
},
),
IconButton(
alignment: Alignment.center,
icon: Icon(
Icons.keyboard_arrow_down,
color: Colors.blueGrey,
),
onPressed: () {
_moveServerDown(index);
},
),
IconButton( IconButton(
alignment: Alignment.center, alignment: Alignment.center,
icon: Icon( icon: Icon(
@ -375,38 +395,59 @@ class _ServerListState extends State<ServerList> {
} }
static Future<ServerStatus> _checkStatus(String uri) async { static Future<ServerStatus> _checkStatus(String uri) async {
Uri parsedUri;
try { try {
parsedUri = Uri.parse(uri); Uri parsedUri;
} catch (FormatException) {
return ServerStatus.dnsError;
}
try {
await HttpUtils.getForFullResponse('https://dns.google.com');
} catch (SocketException) {
return ServerStatus.clientConnectivityIssues;
}
try {
// Check if host is IP address
InternetAddress(parsedUri.host);
} catch (ArgumentError) /* Host is a DNS name */ {
var v4recs, v6recs;
try { try {
v4recs = await DnsUtils.lookupRecord(parsedUri.host, RRecordType.A); parsedUri = Uri.parse(uri);
v6recs = await DnsUtils.lookupRecord(parsedUri.host, RRecordType.AAAA); } on FormatException {
} catch (SocketException) {
return ServerStatus.clientConnectivityIssues;
}
var v4 = await _resolveHostname(v4recs, RRecordType.A);
var v6 = await _resolveHostname(v6recs, RRecordType.AAAA);
if (v4 == null && v6 == null) {
return ServerStatus.dnsError; return ServerStatus.dnsError;
} }
try {
// Check if host is IP address
var ip = InternetAddress(parsedUri.host);
InternetAddress reversedIp = await ip.reverse();
if (ip.host != reversedIp.host) {
parsedUri = parsedUri.replace(host: reversedIp.host);
throw ArgumentError("Valid IP, but trying with reverse hostname...");
}
if (parsedUri.scheme == "https") return ServerStatus.certificateError;
} on ArgumentError /* Host is a DNS name */ {
List<RRecord> v4recs, v6recs;
try {
try {
v4recs = await DnsUtils.lookupRecord(parsedUri.host, RRecordType.A);
} on HttpResponseException {
v4recs = [];
}
try {
v6recs =
await DnsUtils.lookupRecord(parsedUri.host, RRecordType.AAAA);
} on HttpResponseException {
v6recs = [];
}
} on SocketException catch (e) {
return ServerStatus.clientConnectivityIssues;
}
var v4 = await _resolveHostname(v4recs, RRecordType.A);
var v6 = await _resolveHostname(v6recs, RRecordType.AAAA);
if (v4 == null && v6 == null) {
return ServerStatus.dnsError;
}
}
try {
return await _checkResponse(parsedUri);
} on TlsException {
return ServerStatus.certificateError;
}
} on SocketException catch (e) {
// Network unreachable
if (e.osError.errorCode == 101)
return ServerStatus.clientConnectivityIssues;
throw e;
} }
return await _checkResponse(parsedUri);
} }
Icon _generateIcon(Server server) { Icon _generateIcon(Server server) {
@ -436,6 +477,10 @@ class _ServerListState extends State<ServerList> {
icon = Icons.signal_wifi_off; icon = Icons.signal_wifi_off;
color = Colors.red.shade400; color = Colors.red.shade400;
break; break;
case ServerStatus.certificateError:
icon = Icons.security;
color = Colors.yellow.shade400;
break;
default: default:
icon = Icons.device_unknown; icon = Icons.device_unknown;
color = Colors.blueGrey.shade400; color = Colors.blueGrey.shade400;
@ -465,7 +510,7 @@ class _ServerListState extends State<ServerList> {
try { try {
response = await HttpUtils.getForFullResponse(uri.toString()) response = await HttpUtils.getForFullResponse(uri.toString())
.timeout(new Duration(seconds: 3)); .timeout(new Duration(seconds: 3));
} catch (TimeoutException) { } on TimeoutException {
return ServerStatus.timeout; return ServerStatus.timeout;
} }
@ -526,17 +571,48 @@ class _ServerListState extends State<ServerList> {
case ServerStatus.unknown: case ServerStatus.unknown:
return 'Loading...'; return 'Loading...';
case ServerStatus.ok: case ServerStatus.ok:
return 'Reachable'; return 'Reachable.';
case ServerStatus.notOk: case ServerStatus.notOk:
return 'Unexpected response'; return 'Unexpected response received.';
case ServerStatus.timeout: case ServerStatus.timeout:
return 'Timeout'; return 'Server took more than 3 seconds to respond.';
case ServerStatus.dnsError: case ServerStatus.dnsError:
return 'DNS issues'; return 'DNS issues.';
case ServerStatus.clientConnectivityIssues: case ServerStatus.clientConnectivityIssues:
return 'Connectivity issues on your device'; return 'Connectivity issues on your device.';
case ServerStatus.certificateError:
return 'A secure connection could not be established.';
default: default:
return ''; return '';
} }
} }
void _moveServer(int index, AxisDirection direction) {
int newIndex;
switch (direction) {
case AxisDirection.up:
if (index == 0) return;
newIndex = index - 1;
break;
case AxisDirection.down:
if (index == servers.length - 1) return;
newIndex = index + 1;
break;
default:
return;
break;
}
Server server = servers[index];
servers.removeAt(index);
setState(() {
servers.insert(newIndex, server);
selectedServer = newIndex;
});
_saveServersToPreferences();
}
void _moveServerUp(int index) => _moveServer(index, AxisDirection.up);
void _moveServerDown(int index) => _moveServer(index, AxisDirection.down);
} }