blob: 3e476eae08d7b97fbc31873e1a746b8896d8f2d3 [file] [log] [blame]
// 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";
/// 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>[];
final server = await RawServerSocket.bind(serverAddr, 0);
server.listen(makeListener(remotePorts));
bool success = false;
try {
final 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 {
final server = await RawServerSocket.bind(address, 0);
server.listen(makeListener());
bool testFailure = false;
try {
final 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);
}