finalize app for presentation tomorrow #35
2 changed files with 110 additions and 33 deletions
|
@ -4,7 +4,8 @@ enum ServerStatus {
|
|||
notOk,
|
||||
timeout,
|
||||
dnsError,
|
||||
clientConnectivityIssues
|
||||
clientConnectivityIssues,
|
||||
certificateError
|
||||
}
|
||||
|
||||
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(
|
||||
alignment: Alignment.center,
|
||||
icon: Icon(
|
||||
|
@ -375,29 +395,39 @@ class _ServerListState extends State<ServerList> {
|
|||
}
|
||||
|
||||
static Future<ServerStatus> _checkStatus(String uri) async {
|
||||
try {
|
||||
Uri parsedUri;
|
||||
|
||||
try {
|
||||
parsedUri = Uri.parse(uri);
|
||||
} catch (FormatException) {
|
||||
} on 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;
|
||||
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);
|
||||
v6recs = await DnsUtils.lookupRecord(parsedUri.host, RRecordType.AAAA);
|
||||
} catch (SocketException) {
|
||||
} 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);
|
||||
|
@ -406,7 +436,18 @@ class _ServerListState extends State<ServerList> {
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
||||
Icon _generateIcon(Server server) {
|
||||
|
@ -436,6 +477,10 @@ class _ServerListState extends State<ServerList> {
|
|||
icon = Icons.signal_wifi_off;
|
||||
color = Colors.red.shade400;
|
||||
break;
|
||||
case ServerStatus.certificateError:
|
||||
icon = Icons.security;
|
||||
color = Colors.yellow.shade400;
|
||||
break;
|
||||
default:
|
||||
icon = Icons.device_unknown;
|
||||
color = Colors.blueGrey.shade400;
|
||||
|
@ -465,7 +510,7 @@ class _ServerListState extends State<ServerList> {
|
|||
try {
|
||||
response = await HttpUtils.getForFullResponse(uri.toString())
|
||||
.timeout(new Duration(seconds: 3));
|
||||
} catch (TimeoutException) {
|
||||
} on TimeoutException {
|
||||
return ServerStatus.timeout;
|
||||
}
|
||||
|
||||
|
@ -526,17 +571,48 @@ class _ServerListState extends State<ServerList> {
|
|||
case ServerStatus.unknown:
|
||||
return 'Loading...';
|
||||
case ServerStatus.ok:
|
||||
return 'Reachable';
|
||||
return 'Reachable.';
|
||||
case ServerStatus.notOk:
|
||||
return 'Unexpected response';
|
||||
return 'Unexpected response received.';
|
||||
case ServerStatus.timeout:
|
||||
return 'Timeout';
|
||||
return 'Server took more than 3 seconds to respond.';
|
||||
case ServerStatus.dnsError:
|
||||
return 'DNS issues';
|
||||
return 'DNS issues.';
|
||||
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:
|
||||
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