myIPs method
Retrieves both the IPv4 and IPv6 addresses of this client as seen by the remote server.
The current connection only reveals the address of the family it was established over. To discover the other family, an auxiliary connection is opened (forced to that family, authenticated with the same access key) and queried with myIP.
A slot is null when that family could not be determined (e.g. the server
is not reachable over it, or host is a literal address of the other
family).
Implementation
Future<({String? ipv4, String? ipv6})> myIPs() async {
String? ipv4;
String? ipv6;
// Current connection: classify its server-visible address by family.
var currentType = _socket?.remoteAddress.type;
var currentIp = await myIP();
if (currentIp != null) {
if (isIPv6Address(currentIp)) {
ipv6 = currentIp;
} else {
ipv4 = currentIp;
}
}
// Discover the missing family via an auxiliary connection.
Future<String?> discover(InternetAddressType type) async {
final accessKey = _accessKey;
if (accessKey == null) return null;
final auxClient =
GatekeeperClient(host, port, secure: secure, verbose: verbose);
try {
var connected = await auxClient.connect(addressType: type);
if (!connected) return null;
var login = await auxClient.login(accessKey);
if (!login.ok) return null;
return await auxClient.myIP();
} catch (_) {
return null;
} finally {
auxClient.close();
}
}
if (ipv4 == null && currentType != InternetAddressType.IPv4) {
try {
ipv4 = await discover(InternetAddressType.IPv4);
} catch (_) {}
}
if (ipv6 == null && currentType != InternetAddressType.IPv6) {
try {
ipv6 = await discover(InternetAddressType.IPv6);
} catch (_) {}
}
return (ipv4: ipv4, ipv6: ipv6);
}