finalize app for presentation tomorrow #35
2 changed files with 110 additions and 33 deletions
|
@ -4,7 +4,8 @@ enum ServerStatus {
|
||||||
notOk,
|
notOk,
|
||||||
timeout,
|
timeout,
|
||||||
dnsError,
|
dnsError,
|
||||||
clientConnectivityIssues
|
clientConnectivityIssues,
|
||||||
|
certificateError
|
||||||
}
|
}
|
||||||
|
|
||||||
class Server {
|
class Server {
|
||||||
|
|
|
@ -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,29 +395,39 @@ class _ServerListState extends State<ServerList> {
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<ServerStatus> _checkStatus(String uri) async {
|
static Future<ServerStatus> _checkStatus(String uri) async {
|
||||||
|
try {
|
||||||
Uri parsedUri;
|
Uri parsedUri;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
parsedUri = Uri.parse(uri);
|
parsedUri = Uri.parse(uri);
|
||||||
} catch (FormatException) {
|
} on FormatException {
|
||||||
return ServerStatus.dnsError;
|
return ServerStatus.dnsError;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
await HttpUtils.getForFullResponse('https://dns.google.com');
|
|
||||||
} catch (SocketException) {
|
|
||||||
return ServerStatus.clientConnectivityIssues;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Check if host is IP address
|
// Check if host is IP address
|
||||||
InternetAddress(parsedUri.host);
|
var ip = InternetAddress(parsedUri.host);
|
||||||
} catch (ArgumentError) /* Host is a DNS name */ {
|
InternetAddress reversedIp = await ip.reverse();
|
||||||
var v4recs, v6recs;
|
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 {
|
try {
|
||||||
v4recs = await DnsUtils.lookupRecord(parsedUri.host, RRecordType.A);
|
v4recs = await DnsUtils.lookupRecord(parsedUri.host, RRecordType.A);
|
||||||
v6recs = await DnsUtils.lookupRecord(parsedUri.host, RRecordType.AAAA);
|
} on HttpResponseException {
|
||||||
} catch (SocketException) {
|
v4recs = [];
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
v6recs =
|
||||||
|
await DnsUtils.lookupRecord(parsedUri.host, RRecordType.AAAA);
|
||||||
|
} on HttpResponseException {
|
||||||
|
v6recs = [];
|
||||||
|
}
|
||||||
|
} on SocketException catch (e) {
|
||||||
return ServerStatus.clientConnectivityIssues;
|
return ServerStatus.clientConnectivityIssues;
|
||||||
}
|
}
|
||||||
var v4 = await _resolveHostname(v4recs, RRecordType.A);
|
var v4 = await _resolveHostname(v4recs, RRecordType.A);
|
||||||
|
@ -406,7 +436,18 @@ class _ServerListState extends State<ServerList> {
|
||||||
return ServerStatus.dnsError;
|
return ServerStatus.dnsError;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
return await _checkResponse(parsedUri);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue