[dart:io] Parse scoped IPv6 in constructor of InternetAddress

Bug: https://github.com/dart-lang/sdk/issues/41663
Change-Id: Ic7a140bc335e56550e39bb30390247db668c6101
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/147060
Commit-Queue: Zichang Guo <zichangguo@google.com>
Reviewed-by: Jonas Termansen <sortie@google.com>
Reviewed-by: Zach Anderson <zra@google.com>
This commit is contained in:
Zichang Guo 2020-07-24 00:43:35 +00:00 committed by commit-bot@chromium.org
parent c2d28d1569
commit d2f7039e9c
5 changed files with 76 additions and 17 deletions

View file

@ -82,6 +82,7 @@ namespace bin {
V(Filter_Process, 4) \
V(Filter_Processed, 3) \
V(InternetAddress_Parse, 1) \
V(InternetAddress_ParseScopedLinkLocalAddress, 1) \
V(InternetAddress_RawAddrToString, 1) \
V(IOService_NewServicePort, 0) \
V(Namespace_Create, 2) \

View file

@ -243,6 +243,31 @@ void FUNCTION_NAME(InternetAddress_Parse)(Dart_NativeArguments args) {
}
}
void FUNCTION_NAME(InternetAddress_ParseScopedLinkLocalAddress)(
Dart_NativeArguments args) {
const char* address =
DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0));
// This must be an IPv6 address.
intptr_t type = 1;
ASSERT(address != NULL);
OSError* os_error = NULL;
AddressList<SocketAddress>* addresses =
SocketBase::LookupAddress(address, type, &os_error);
if (addresses != NULL) {
Dart_Handle list = Dart_NewList(addresses->count());
for (intptr_t i = 0; i < addresses->count(); i++) {
SocketAddress* addr = addresses->GetAt(i);
Dart_ListSetAt(
list, i, Dart_NewInteger(SocketAddress::GetAddrScope(addr->addr())));
}
delete addresses;
Dart_SetReturnValue(args, list);
} else {
Dart_SetReturnValue(args, DartUtils::NewDartOSError(os_error));
delete os_error;
}
}
void FUNCTION_NAME(InternetAddress_RawAddrToString)(Dart_NativeArguments args) {
RawAddr addr;
SocketAddress::GetSockAddr(Dart_GetNativeArgument(args, 0), &addr);

View file

@ -226,14 +226,36 @@ class _InternetAddress implements InternetAddress {
return _InternetAddress(
InternetAddressType.unix, address, null, rawAddress);
} else {
var in_addr = _parse(address);
if (in_addr == null) {
throw ArgumentError("Invalid internet address $address");
int index = address.indexOf('%');
String originalAddress = address;
String? scopeID;
if (index > 0) {
scopeID = address.substring(index, address.length);
address = address.substring(0, index);
}
InternetAddressType type = in_addr.length == _IPv4AddrLength
var inAddr = _parse(address);
if (inAddr == null) {
throw ArgumentError.value("Invalid internet address $address");
}
InternetAddressType type = inAddr.length == _IPv4AddrLength
? InternetAddressType.IPv4
: InternetAddressType.IPv6;
return _InternetAddress(type, address, null, in_addr);
if (scopeID != null && scopeID.length > 0) {
if (type != InternetAddressType.IPv6) {
throw ArgumentError.value("IPv4 addresses cannot have a scope id");
}
// This is an IPv6 address with scope id.
var list = _parseScopedLinkLocalAddress(originalAddress);
if (list is! OSError && (list as List).isNotEmpty) {
return _InternetAddress(InternetAddressType.IPv6, originalAddress,
null, inAddr, list.first);
} else {
throw ArgumentError.value(
"Invalid IPv6 address $address with scope ID");
}
}
return _InternetAddress(type, originalAddress, null, inAddr, 0);
}
}
@ -262,12 +284,11 @@ class _InternetAddress implements InternetAddress {
static _InternetAddress? tryParse(String address) {
checkNotNullable(address, "address");
var addressBytes = _parse(address);
if (addressBytes == null) return null;
var type = addressBytes.length == _IPv4AddrLength
? InternetAddressType.IPv4
: InternetAddressType.IPv6;
return _InternetAddress(type, address, null, addressBytes);
try {
return _InternetAddress.fromString(address);
} catch (e) {
return null;
}
}
factory _InternetAddress.fixed(int id) {
@ -297,7 +318,8 @@ class _InternetAddress implements InternetAddress {
// Create a clone of this _InternetAddress replacing the host.
_InternetAddress _cloneWithNewHost(String host) {
return _InternetAddress(type, address, host, Uint8List.fromList(_in_addr));
return _InternetAddress(
type, address, host, Uint8List.fromList(_in_addr), _scope_id);
}
bool operator ==(other) {
@ -330,7 +352,8 @@ class _InternetAddress implements InternetAddress {
static String _rawAddrToString(Uint8List address)
native "InternetAddress_RawAddrToString";
static List _parseScopedLinkLocalAddress(String address)
native "InternetAddress_ParseScopedLinkLocalAddress";
static Uint8List? _parse(String address) native "InternetAddress_Parse";
}

View file

@ -16,8 +16,13 @@ void main() {
// ip address show
asyncStart();
try {
// Make sure the address here is the same as what it shows in "ip address show"
var ipv6 = 'fe80:1::10%tap0';
// Make sure the address here is the same as what it shows in
// "ip address show"
var ipv6 = 'fe80:1::1%tap0';
// Parses a Link-local address on Linux and Windows will throw an exception.
InternetAddress(ipv6);
HttpServer.bind(ipv6, 0).then((server) {
server.listen((request) {
var timer = new Timer.periodic(const Duration(milliseconds: 0), (_) {

View file

@ -16,8 +16,13 @@ void main() {
// ip address show
asyncStart();
try {
// Make sure the address here is the same as what it shows in "ip address show"
var ipv6 = 'fe80:1::10%tap0';
// Make sure the address here is the same as what it shows in
// "ip address show"
var ipv6 = 'fe80:1::1%tap0';
// Parses a Link-local address on Linux and Windows will throw an exception.
InternetAddress(ipv6);
HttpServer.bind(ipv6, 0).then((server) {
server.listen((request) {
var timer = new Timer.periodic(const Duration(milliseconds: 0), (_) {