e6e88c719c
This test checks that we should not be able to connect to server listening on IPv4 via IPv6 and vice versa. However by chance some other test might start listening on the same port as this test is using, just using different protocol. In this case the test will fail. To make this test more robust we add a check which verifies that server did not actually see the connection from the client with a matching port (we compare client's port to remotePort that server saw). After these changes we only should fail this test if we indeed managed to connect to the loopback server using a mismatching protocol. Fixes https://github.com/dart-lang/sdk/issues/30700 Change-Id: Ib4f3d0346030dcffaac44ff5dd4050939984b1fc Reviewed-on: https://dart-review.googlesource.com/c/85389 Commit-Queue: Vyacheslav Egorov <vegorov@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
81 lines
2.7 KiB
Dart
81 lines
2.7 KiB
Dart
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
import "dart:async";
|
|
import "dart:io";
|
|
import "package:expect/expect.dart";
|
|
|
|
RawServerSocket server;
|
|
RawSocket client;
|
|
|
|
/// Creates a callback that listens for incomming connections.
|
|
/// If [remotePorts] is not null then callback would add remote port of each
|
|
/// new connection to the given list.
|
|
makeListener([List<int> remotePorts]) {
|
|
return (RawSocket serverSide) {
|
|
serveData(RawSocketEvent event) {
|
|
serverSide.shutdown(SocketDirection.send);
|
|
}
|
|
|
|
remotePorts?.add(serverSide.remotePort);
|
|
serverSide.listen(serveData);
|
|
};
|
|
}
|
|
|
|
/// Verify that you can't connect to loopback via mismatching protocol, e.g.
|
|
/// if the server is listening to IPv4 then you can't connect via IPv6.
|
|
Future<void> failureTest(
|
|
InternetAddress serverAddr, InternetAddress clientAddr) async {
|
|
final remotePorts = <int>[];
|
|
server = await RawServerSocket.bind(serverAddr, 0);
|
|
server.listen(makeListener(remotePorts));
|
|
|
|
bool success = false;
|
|
try {
|
|
client = await RawSocket.connect(clientAddr, server.port);
|
|
final clientPort = client.port;
|
|
|
|
// We might actually succeed in connecting somewhere (e.g. to another test
|
|
// which by chance started listening to the same port).
|
|
// To make this test more robust we add a check that verifies that we did
|
|
// not connect to our server by checking if clientPort is within
|
|
// the list of remotePorts observed by the server. It should not be there.
|
|
await Future.delayed(Duration(seconds: 2));
|
|
success = !remotePorts.contains(clientPort);
|
|
await client.close();
|
|
} on SocketException catch (e) {
|
|
// We expect that we fail to connect to IPv4 server via IPv6 client and
|
|
// vice versa.
|
|
success = true;
|
|
} catch (e) {
|
|
Expect.fail('Unexpected exception: $e');
|
|
} finally {
|
|
Expect.isTrue(success,
|
|
'Unexpected connection to $serverAddr via $clientAddr address!');
|
|
await server.close();
|
|
}
|
|
}
|
|
|
|
Future<void> successTest(InternetAddress address) async {
|
|
server = await RawServerSocket.bind(address, 0);
|
|
server.listen(makeListener());
|
|
bool testFailure = false;
|
|
try {
|
|
client = await RawSocket.connect(address, server.port);
|
|
await client.close();
|
|
} catch (e) {
|
|
testFailure = true;
|
|
} finally {
|
|
Expect.equals(testFailure, false);
|
|
await server.close();
|
|
}
|
|
}
|
|
|
|
main() async {
|
|
await failureTest(InternetAddress.loopbackIPv4, InternetAddress.loopbackIPv6);
|
|
await failureTest(InternetAddress.loopbackIPv6, InternetAddress.loopbackIPv4);
|
|
await successTest(InternetAddress.loopbackIPv4);
|
|
await successTest(InternetAddress.loopbackIPv6);
|
|
}
|