Added sourcePort to Socket.connect()/startConnect() as optional parameter.
This allows to specify the local port for TCP client sockets. All prototypes in Socket,RawSocket,_Rawsocket,_NativeSocket have been adopted, aswell as the native counterpart to nativeCreateBindConnect. TEST=new tests added Change-Id: I3408b687cbfd7eaaaeafdda29f7093d92c92aea0 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/217604 Reviewed-by: Siva Annamalai <asiva@google.com> Auto-Submit: Moritz Feldmann <moritz.feldmann@kabelmail.de> Reviewed-by: Kevin Moore <kevmoo@google.com> Commit-Queue: Kevin Moore <kevmoo@google.com>
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
- **Breaking Change** [#47769](https://github.com/dart-lang/sdk/issues/47769):
|
||||
The `Platform.packageRoot` API has been removed. It had been marked deprecated
|
||||
in 2018, as it doesn't work with any Dart 2.x release.
|
||||
- Add optional `sourcePort` parameter to `Socket.connect`, `Socket.startConnect`, `RawSocket.connect` and `RawSocket.startConnect`
|
||||
|
||||
#### `dart:isolate`
|
||||
|
||||
|
||||
@@ -144,7 +144,7 @@ namespace bin {
|
||||
V(SocketBase_IsBindError, 2) \
|
||||
V(Socket_Available, 1) \
|
||||
V(Socket_AvailableDatagram, 1) \
|
||||
V(Socket_CreateBindConnect, 5) \
|
||||
V(Socket_CreateBindConnect, 6) \
|
||||
V(Socket_CreateUnixDomainBindConnect, 4) \
|
||||
V(Socket_CreateBindDatagram, 6) \
|
||||
V(Socket_CreateConnect, 4) \
|
||||
|
||||
@@ -396,8 +396,13 @@ void FUNCTION_NAME(Socket_CreateBindConnect)(Dart_NativeArguments args) {
|
||||
SocketAddress::SetAddrPort(&addr, static_cast<intptr_t>(port));
|
||||
RawAddr sourceAddr;
|
||||
SocketAddress::GetSockAddr(Dart_GetNativeArgument(args, 3), &sourceAddr);
|
||||
Dart_Handle source_port_arg = Dart_GetNativeArgument(args, 4);
|
||||
int64_t source_port =
|
||||
DartUtils::GetInt64ValueCheckRange(source_port_arg, 0, 65535);
|
||||
SocketAddress::SetAddrPort(&sourceAddr, static_cast<intptr_t>(source_port));
|
||||
|
||||
if (addr.addr.sa_family == AF_INET6) {
|
||||
Dart_Handle scope_id_arg = Dart_GetNativeArgument(args, 4);
|
||||
Dart_Handle scope_id_arg = Dart_GetNativeArgument(args, 5);
|
||||
int64_t scope_id =
|
||||
DartUtils::GetInt64ValueCheckRange(scope_id_arg, 0, 65535);
|
||||
SocketAddress::SetAddrScope(&addr, scope_id);
|
||||
|
||||
@@ -475,13 +475,13 @@ class ServerSocket {
|
||||
class RawSocket {
|
||||
@patch
|
||||
static Future<RawSocket> connect(dynamic host, int port,
|
||||
{dynamic sourceAddress, Duration? timeout}) {
|
||||
{dynamic sourceAddress, int sourcePort = 0, Duration? timeout}) {
|
||||
throw UnsupportedError("RawSocket constructor");
|
||||
}
|
||||
|
||||
@patch
|
||||
static Future<ConnectionTask<RawSocket>> startConnect(dynamic host, int port,
|
||||
{dynamic sourceAddress}) {
|
||||
{dynamic sourceAddress, int sourcePort = 0}) {
|
||||
throw UnsupportedError("RawSocket constructor");
|
||||
}
|
||||
}
|
||||
@@ -490,13 +490,13 @@ class RawSocket {
|
||||
class Socket {
|
||||
@patch
|
||||
static Future<Socket> _connect(dynamic host, int port,
|
||||
{dynamic sourceAddress, Duration? timeout}) {
|
||||
{dynamic sourceAddress, int sourcePort = 0, Duration? timeout}) {
|
||||
throw UnsupportedError("Socket constructor");
|
||||
}
|
||||
|
||||
@patch
|
||||
static Future<ConnectionTask<Socket>> _startConnect(dynamic host, int port,
|
||||
{dynamic sourceAddress}) {
|
||||
{dynamic sourceAddress, int sourcePort = 0}) {
|
||||
throw UnsupportedError("Socket constructor");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -475,13 +475,13 @@ class ServerSocket {
|
||||
class RawSocket {
|
||||
@patch
|
||||
static Future<RawSocket> connect(dynamic host, int port,
|
||||
{dynamic sourceAddress, Duration? timeout}) {
|
||||
{dynamic sourceAddress, int sourcePort = 0, Duration? timeout}) {
|
||||
throw new UnsupportedError("RawSocket constructor");
|
||||
}
|
||||
|
||||
@patch
|
||||
static Future<ConnectionTask<RawSocket>> startConnect(dynamic host, int port,
|
||||
{dynamic sourceAddress}) {
|
||||
{dynamic sourceAddress, int sourcePort = 0}) {
|
||||
throw new UnsupportedError("RawSocket constructor");
|
||||
}
|
||||
}
|
||||
@@ -490,13 +490,13 @@ class RawSocket {
|
||||
class Socket {
|
||||
@patch
|
||||
static Future<Socket> _connect(dynamic host, int port,
|
||||
{dynamic sourceAddress, Duration? timeout}) {
|
||||
{dynamic sourceAddress, int sourcePort = 0, Duration? timeout}) {
|
||||
throw new UnsupportedError("Socket constructor");
|
||||
}
|
||||
|
||||
@patch
|
||||
static Future<ConnectionTask<Socket>> _startConnect(dynamic host, int port,
|
||||
{dynamic sourceAddress}) {
|
||||
{dynamic sourceAddress, int sourcePort = 0}) {
|
||||
throw new UnsupportedError("Socket constructor");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,14 +17,14 @@ class RawServerSocket {
|
||||
class RawSocket {
|
||||
@patch
|
||||
static Future<RawSocket> connect(dynamic host, int port,
|
||||
{dynamic sourceAddress, Duration? timeout}) {
|
||||
return _RawSocket.connect(host, port, sourceAddress, timeout);
|
||||
{dynamic sourceAddress, int sourcePort = 0, Duration? timeout}) {
|
||||
return _RawSocket.connect(host, port, sourceAddress, sourcePort, timeout);
|
||||
}
|
||||
|
||||
@patch
|
||||
static Future<ConnectionTask<RawSocket>> startConnect(dynamic host, int port,
|
||||
{dynamic sourceAddress}) {
|
||||
return _RawSocket.startConnect(host, port, sourceAddress);
|
||||
{dynamic sourceAddress, int sourcePort = 0}) {
|
||||
return _RawSocket.startConnect(host, port, sourceAddress, sourcePort);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -654,7 +654,7 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
|
||||
}
|
||||
|
||||
static Future<ConnectionTask<_NativeSocket>> startConnect(
|
||||
dynamic host, int port, dynamic sourceAddress) {
|
||||
dynamic host, int port, dynamic sourceAddress, int sourcePort) {
|
||||
// Looks up [sourceAddress] to one or more IP addresses,
|
||||
// then tries connecting to each one until a connection succeeds.
|
||||
// Attempts are staggered by a minimum delay, so a new
|
||||
@@ -666,6 +666,7 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
|
||||
host = escapeLinkLocalAddress(host);
|
||||
}
|
||||
_throwOnBadPort(port);
|
||||
_throwOnBadPort(sourcePort);
|
||||
_InternetAddress? source;
|
||||
if (sourceAddress != null) {
|
||||
if (sourceAddress is _InternetAddress) {
|
||||
@@ -682,7 +683,7 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
|
||||
|
||||
return new Future.value(host).then<ConnectionTask<_NativeSocket>>((host) {
|
||||
if (host is _InternetAddress) {
|
||||
return tryConnectToResolvedAddresses(host, port, source,
|
||||
return tryConnectToResolvedAddresses(host, port, source, sourcePort,
|
||||
Stream.value(<_InternetAddress>[host]), stackTrace);
|
||||
}
|
||||
final hostname = host as String;
|
||||
@@ -700,7 +701,7 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
|
||||
: lookupAsStream(hostname);
|
||||
|
||||
return tryConnectToResolvedAddresses(
|
||||
host, port, source, stream, stackTrace);
|
||||
host, port, source, sourcePort, stream, stackTrace);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -708,6 +709,7 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
|
||||
dynamic host,
|
||||
int port,
|
||||
_InternetAddress? source,
|
||||
int sourcePort,
|
||||
Stream<List<InternetAddress>> addresses,
|
||||
StackTrace callerStackTrace) {
|
||||
// Completer for result.
|
||||
@@ -758,10 +760,16 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
|
||||
connectionResult is OSError);
|
||||
} else {
|
||||
final address_ = address as _InternetAddress;
|
||||
if (source == null) {
|
||||
if (source == null && sourcePort == 0) {
|
||||
connectionResult = socket.nativeCreateConnect(
|
||||
address_._in_addr, port, address_._scope_id);
|
||||
} else {
|
||||
// allow specified port without address
|
||||
if (source == null) {
|
||||
source = address_.type == InternetAddressType.IPv4
|
||||
? _InternetAddress.anyIPv4
|
||||
: _InternetAddress.anyIPv6;
|
||||
}
|
||||
if (source.type != InternetAddressType.IPv4 &&
|
||||
source.type != InternetAddressType.IPv6) {
|
||||
return SocketException(
|
||||
@@ -773,8 +781,8 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
|
||||
"${InternetAddressType.IPv6} but was ${source.type}",
|
||||
address: address);
|
||||
}
|
||||
connectionResult = socket.nativeCreateBindConnect(
|
||||
address_._in_addr, port, source._in_addr, address_._scope_id);
|
||||
connectionResult = socket.nativeCreateBindConnect(address_._in_addr,
|
||||
port, source._in_addr, sourcePort, address_._scope_id);
|
||||
}
|
||||
assert(connectionResult == true || connectionResult is OSError);
|
||||
}
|
||||
@@ -935,9 +943,9 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
|
||||
return new ConnectionTask<_NativeSocket>._(result.future, onCancel);
|
||||
}
|
||||
|
||||
static Future<_NativeSocket> connect(
|
||||
dynamic host, int port, dynamic sourceAddress, Duration? timeout) {
|
||||
return startConnect(host, port, sourceAddress)
|
||||
static Future<_NativeSocket> connect(dynamic host, int port,
|
||||
dynamic sourceAddress, int sourcePort, Duration? timeout) {
|
||||
return startConnect(host, port, sourceAddress, sourcePort)
|
||||
.then((ConnectionTask<_NativeSocket> task) {
|
||||
Future<_NativeSocket> socketFuture = task.socket;
|
||||
if (timeout != null) {
|
||||
@@ -1653,8 +1661,8 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
|
||||
@pragma("vm:external-name", "Socket_CreateUnixDomainConnect")
|
||||
external nativeCreateUnixDomainConnect(String addr, _Namespace namespace);
|
||||
@pragma("vm:external-name", "Socket_CreateBindConnect")
|
||||
external nativeCreateBindConnect(
|
||||
Uint8List addr, int port, Uint8List sourceAddr, int scope_id);
|
||||
external nativeCreateBindConnect(Uint8List addr, int port,
|
||||
Uint8List sourceAddr, int sourcePort, int scope_id);
|
||||
@pragma("vm:external-name", "Socket_CreateUnixDomainBindConnect")
|
||||
external nativeCreateUnixDomainBindConnect(
|
||||
String addr, String sourceAddr, _Namespace namespace);
|
||||
@@ -1792,9 +1800,9 @@ class _RawSocket extends Stream<RawSocketEvent> implements RawSocket {
|
||||
// Flag to handle Ctrl-D closing of stdio on Mac OS.
|
||||
bool _isMacOSTerminalInput = false;
|
||||
|
||||
static Future<RawSocket> connect(
|
||||
dynamic host, int port, dynamic sourceAddress, Duration? timeout) {
|
||||
return _NativeSocket.connect(host, port, sourceAddress, timeout)
|
||||
static Future<RawSocket> connect(dynamic host, int port,
|
||||
dynamic sourceAddress, int sourcePort, Duration? timeout) {
|
||||
return _NativeSocket.connect(host, port, sourceAddress, sourcePort, timeout)
|
||||
.then((socket) {
|
||||
if (!const bool.fromEnvironment("dart.vm.product")) {
|
||||
_SocketProfile.collectNewSocket(
|
||||
@@ -1805,8 +1813,8 @@ class _RawSocket extends Stream<RawSocketEvent> implements RawSocket {
|
||||
}
|
||||
|
||||
static Future<ConnectionTask<_RawSocket>> startConnect(
|
||||
dynamic host, int port, dynamic sourceAddress) {
|
||||
return _NativeSocket.startConnect(host, port, sourceAddress)
|
||||
dynamic host, int port, dynamic sourceAddress, int sourcePort) {
|
||||
return _NativeSocket.startConnect(host, port, sourceAddress, sourcePort)
|
||||
.then((ConnectionTask<_NativeSocket> nativeTask) {
|
||||
final Future<_RawSocket> raw =
|
||||
nativeTask.socket.then((_NativeSocket nativeSocket) {
|
||||
@@ -2016,16 +2024,19 @@ class _ServerSocket extends Stream<Socket> implements ServerSocket {
|
||||
class Socket {
|
||||
@patch
|
||||
static Future<Socket> _connect(dynamic host, int port,
|
||||
{dynamic sourceAddress, Duration? timeout}) {
|
||||
{dynamic sourceAddress, int sourcePort = 0, Duration? timeout}) {
|
||||
return RawSocket.connect(host, port,
|
||||
sourceAddress: sourceAddress, timeout: timeout)
|
||||
sourceAddress: sourceAddress,
|
||||
sourcePort: sourcePort,
|
||||
timeout: timeout)
|
||||
.then((socket) => new _Socket(socket));
|
||||
}
|
||||
|
||||
@patch
|
||||
static Future<ConnectionTask<Socket>> _startConnect(dynamic host, int port,
|
||||
{dynamic sourceAddress}) {
|
||||
return RawSocket.startConnect(host, port, sourceAddress: sourceAddress)
|
||||
{dynamic sourceAddress, int sourcePort = 0}) {
|
||||
return RawSocket.startConnect(host, port,
|
||||
sourceAddress: sourceAddress, sourcePort: sourcePort)
|
||||
.then((rawTask) {
|
||||
Future<Socket> socket =
|
||||
rawTask.socket.then((rawSocket) => new _Socket(rawSocket));
|
||||
|
||||
+23
-16
@@ -81,10 +81,10 @@ abstract class IOOverrides {
|
||||
|
||||
// Socket
|
||||
Future<Socket> Function(dynamic, int,
|
||||
{dynamic sourceAddress, Duration? timeout})?
|
||||
{dynamic sourceAddress, int sourcePort, Duration? timeout})?
|
||||
socketConnect,
|
||||
Future<ConnectionTask<Socket>> Function(dynamic, int,
|
||||
{dynamic sourceAddress})?
|
||||
{dynamic sourceAddress, int sourcePort})?
|
||||
socketStartConnect,
|
||||
|
||||
// ServerSocket
|
||||
@@ -269,9 +269,9 @@ abstract class IOOverrides {
|
||||
/// When this override is installed, this functions overrides the behavior of
|
||||
/// `Socket.connect(...)`.
|
||||
Future<Socket> socketConnect(host, int port,
|
||||
{sourceAddress, Duration? timeout}) {
|
||||
{sourceAddress, int sourcePort = 0, Duration? timeout}) {
|
||||
return Socket._connect(host, port,
|
||||
sourceAddress: sourceAddress, timeout: timeout);
|
||||
sourceAddress: sourceAddress, sourcePort: sourcePort, timeout: timeout);
|
||||
}
|
||||
|
||||
/// Asynchronously returns a [ConnectionTask] that connects to the given host
|
||||
@@ -280,8 +280,9 @@ abstract class IOOverrides {
|
||||
/// When this override is installed, this functions overrides the behavior of
|
||||
/// `Socket.startConnect(...)`.
|
||||
Future<ConnectionTask<Socket>> socketStartConnect(host, int port,
|
||||
{sourceAddress}) {
|
||||
return Socket._startConnect(host, port, sourceAddress: sourceAddress);
|
||||
{sourceAddress, int sourcePort = 0}) {
|
||||
return Socket._startConnect(host, port,
|
||||
sourceAddress: sourceAddress, sourcePort: sourcePort);
|
||||
}
|
||||
|
||||
// ServerSocket
|
||||
@@ -355,9 +356,11 @@ class _IOOverridesScope extends IOOverrides {
|
||||
|
||||
// Socket
|
||||
Future<Socket> Function(dynamic, int,
|
||||
{dynamic sourceAddress, Duration? timeout})? _socketConnect;
|
||||
{dynamic sourceAddress,
|
||||
int sourcePort,
|
||||
Duration? timeout})? _socketConnect;
|
||||
Future<ConnectionTask<Socket>> Function(dynamic, int,
|
||||
{dynamic sourceAddress})? _socketStartConnect;
|
||||
{dynamic sourceAddress, int sourcePort})? _socketStartConnect;
|
||||
|
||||
// ServerSocket
|
||||
Future<ServerSocket> Function(dynamic, int,
|
||||
@@ -518,30 +521,34 @@ class _IOOverridesScope extends IOOverrides {
|
||||
// Socket
|
||||
@override
|
||||
Future<Socket> socketConnect(host, int port,
|
||||
{sourceAddress, Duration? timeout}) {
|
||||
{sourceAddress, int sourcePort = 0, Duration? timeout}) {
|
||||
if (_socketConnect != null) {
|
||||
return _socketConnect!(host, port,
|
||||
sourceAddress: sourceAddress, timeout: timeout);
|
||||
}
|
||||
if (_previous != null) {
|
||||
return _previous!.socketConnect(host, port,
|
||||
sourceAddress: sourceAddress, timeout: timeout);
|
||||
sourceAddress: sourceAddress,
|
||||
sourcePort: sourcePort,
|
||||
timeout: timeout);
|
||||
}
|
||||
return super.socketConnect(host, port,
|
||||
sourceAddress: sourceAddress, timeout: timeout);
|
||||
sourceAddress: sourceAddress, sourcePort: sourcePort, timeout: timeout);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ConnectionTask<Socket>> socketStartConnect(host, int port,
|
||||
{sourceAddress}) {
|
||||
{sourceAddress, int sourcePort = 0}) {
|
||||
if (_socketStartConnect != null) {
|
||||
return _socketStartConnect!(host, port, sourceAddress: sourceAddress);
|
||||
return _socketStartConnect!(host, port,
|
||||
sourceAddress: sourceAddress, sourcePort: sourcePort);
|
||||
}
|
||||
if (_previous != null) {
|
||||
return _previous!
|
||||
.socketStartConnect(host, port, sourceAddress: sourceAddress);
|
||||
return _previous!.socketStartConnect(host, port,
|
||||
sourceAddress: sourceAddress, sourcePort: sourcePort);
|
||||
}
|
||||
return super.socketStartConnect(host, port, sourceAddress: sourceAddress);
|
||||
return super.socketStartConnect(host, port,
|
||||
sourceAddress: sourceAddress, sourcePort: sourcePort);
|
||||
}
|
||||
|
||||
// ServerSocket
|
||||
|
||||
+19
-10
@@ -589,19 +589,22 @@ abstract class RawSocket implements Stream<RawSocketEvent> {
|
||||
/// be a [String] or an [InternetAddress]. If a [String] is passed it must
|
||||
/// hold a numeric IP address.
|
||||
///
|
||||
/// The [sourcePort] defines the local port to bind to. If [sourcePort] is
|
||||
/// not specified or zero, a port will be chosen.
|
||||
///
|
||||
/// The argument [timeout] is used to specify the maximum allowed time to wait
|
||||
/// for a connection to be established. If [timeout] is longer than the system
|
||||
/// level timeout duration, a timeout may occur sooner than specified in
|
||||
/// [timeout]. On timeout, a [SocketException] is thrown and all ongoing
|
||||
/// connection attempts to [host] are cancelled.
|
||||
external static Future<RawSocket> connect(host, int port,
|
||||
{sourceAddress, Duration? timeout});
|
||||
{sourceAddress, int sourcePort = 0, Duration? timeout});
|
||||
|
||||
/// Like [connect], but returns a [Future] that completes with a
|
||||
/// [ConnectionTask] that can be cancelled if the [RawSocket] is no
|
||||
/// longer needed.
|
||||
external static Future<ConnectionTask<RawSocket>> startConnect(host, int port,
|
||||
{sourceAddress});
|
||||
{sourceAddress, int sourcePort = 0});
|
||||
|
||||
/// The number of received and non-read bytes in the socket that can be read.
|
||||
int available();
|
||||
@@ -758,40 +761,46 @@ abstract class Socket implements Stream<Uint8List>, IOSink {
|
||||
/// be a [String] or an [InternetAddress]. If a [String] is passed it must
|
||||
/// hold a numeric IP address.
|
||||
///
|
||||
/// The [sourcePort] defines the local port to bind to. If [sourcePort] is
|
||||
/// not specified or zero, a port will be chosen.
|
||||
///
|
||||
/// The argument [timeout] is used to specify the maximum allowed time to wait
|
||||
/// for a connection to be established. If [timeout] is longer than the system
|
||||
/// level timeout duration, a timeout may occur sooner than specified in
|
||||
/// [timeout]. On timeout, a [SocketException] is thrown and all ongoing
|
||||
/// connection attempts to [host] are cancelled.
|
||||
static Future<Socket> connect(host, int port,
|
||||
{sourceAddress, Duration? timeout}) {
|
||||
{sourceAddress, int sourcePort = 0, Duration? timeout}) {
|
||||
final IOOverrides? overrides = IOOverrides.current;
|
||||
if (overrides == null) {
|
||||
return Socket._connect(host, port,
|
||||
sourceAddress: sourceAddress, timeout: timeout);
|
||||
sourceAddress: sourceAddress,
|
||||
sourcePort: sourcePort,
|
||||
timeout: timeout);
|
||||
}
|
||||
return overrides.socketConnect(host, port,
|
||||
sourceAddress: sourceAddress, timeout: timeout);
|
||||
sourceAddress: sourceAddress, sourcePort: sourcePort, timeout: timeout);
|
||||
}
|
||||
|
||||
/// Like [connect], but returns a [Future] that completes with a
|
||||
/// [ConnectionTask] that can be cancelled if the [Socket] is no
|
||||
/// longer needed.
|
||||
static Future<ConnectionTask<Socket>> startConnect(host, int port,
|
||||
{sourceAddress}) {
|
||||
{sourceAddress, int sourcePort = 0}) {
|
||||
final IOOverrides? overrides = IOOverrides.current;
|
||||
if (overrides == null) {
|
||||
return Socket._startConnect(host, port, sourceAddress: sourceAddress);
|
||||
return Socket._startConnect(host, port,
|
||||
sourceAddress: sourceAddress, sourcePort: sourcePort);
|
||||
}
|
||||
return overrides.socketStartConnect(host, port,
|
||||
sourceAddress: sourceAddress);
|
||||
sourceAddress: sourceAddress, sourcePort: sourcePort);
|
||||
}
|
||||
|
||||
external static Future<Socket> _connect(host, int port,
|
||||
{sourceAddress, Duration? timeout});
|
||||
{sourceAddress, int sourcePort = 0, Duration? timeout});
|
||||
|
||||
external static Future<ConnectionTask<Socket>> _startConnect(host, int port,
|
||||
{sourceAddress});
|
||||
{sourceAddress, int sourcePort = 0});
|
||||
|
||||
/// Destroys the socket in both directions.
|
||||
///
|
||||
|
||||
@@ -161,12 +161,12 @@ class LinkMock extends FileSystemEntity implements Link {
|
||||
}
|
||||
|
||||
Future<Socket> socketConnect(dynamic host, int port,
|
||||
{dynamic sourceAddress, Duration? timeout}) {
|
||||
{dynamic sourceAddress, int sourcePort = 0, Duration? timeout}) {
|
||||
throw "";
|
||||
}
|
||||
|
||||
Future<ConnectionTask<Socket>> socketStartConnect(dynamic host, int port,
|
||||
{dynamic sourceAddress}) {
|
||||
{dynamic sourceAddress, int sourcePort = 0}) {
|
||||
throw "";
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
// Copyright (c) 2021, 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";
|
||||
|
||||
Future testCustomPortIPv4() async {
|
||||
String clientAddress = "127.0.0.1";
|
||||
int customLocalPort = 50988;
|
||||
String serverAddress = clientAddress;
|
||||
int port = 50989;
|
||||
|
||||
testCustomPort(serverAddress, port, clientAddress, customLocalPort);
|
||||
}
|
||||
|
||||
Future testCustomPortIPv6() async {
|
||||
String clientAddress = "::1";
|
||||
int customLocalPort = 50988;
|
||||
String serverAddress = clientAddress;
|
||||
int port = 50989;
|
||||
|
||||
testCustomPort(serverAddress, port, clientAddress, customLocalPort);
|
||||
}
|
||||
|
||||
Future testCustomPortIPv4NoSourceAddress() async {
|
||||
String expectedClientAddress = "127.0.0.1";
|
||||
int customLocalPort = 50988;
|
||||
String serverAddress = expectedClientAddress;
|
||||
int port = 50989;
|
||||
|
||||
testCustomPort(serverAddress, port, expectedClientAddress, customLocalPort);
|
||||
}
|
||||
|
||||
Future testCustomPortIPv6NoSourceAddress() async {
|
||||
String expectedClientAddress = "::1";
|
||||
int customLocalPort = 50988;
|
||||
String serverAddress = expectedClientAddress;
|
||||
int port = 50989;
|
||||
|
||||
testCustomPort(serverAddress, port, expectedClientAddress, customLocalPort);
|
||||
}
|
||||
|
||||
Future testNoCustomPortIPv4() async {
|
||||
String host = "127.0.0.1";
|
||||
String clientAddress = host;
|
||||
int serverPort = 39998;
|
||||
|
||||
await testNoCustomPortNoSourceAddress(host, serverPort, clientAddress);
|
||||
}
|
||||
|
||||
Future testNoCustomPortIPv6() async {
|
||||
String host = "::1";
|
||||
String clientAddress = host;
|
||||
int serverPort = 39998;
|
||||
|
||||
await testNoCustomPortNoSourceAddress(host, serverPort, clientAddress);
|
||||
}
|
||||
|
||||
Future testNoCustomPortNoSourceAddressIPv4() async {
|
||||
String host = "127.0.0.1";
|
||||
String expectedAddress = host;
|
||||
int serverPort = 39998;
|
||||
|
||||
await testNoCustomPortNoSourceAddress(host, serverPort, expectedAddress);
|
||||
}
|
||||
|
||||
Future testNoCustomPortNoSourceAddressIPv6() async {
|
||||
String host = "::1";
|
||||
String expectedAddress = host;
|
||||
int serverPort = 39998;
|
||||
|
||||
await testNoCustomPortNoSourceAddress(host, serverPort, expectedAddress);
|
||||
}
|
||||
|
||||
// Core functionality
|
||||
void testCustomPort(
|
||||
String host, int port, String sourceAddress, int sourcePort) async {
|
||||
var server = await ServerSocket.bind(host, port);
|
||||
server.listen((client) {
|
||||
Expect.equals(server.port, port);
|
||||
Expect.equals(client.remotePort, sourcePort);
|
||||
Expect.equals(client.address.address, sourceAddress);
|
||||
client.destroy();
|
||||
});
|
||||
|
||||
Socket s = await Socket.connect(host, port,
|
||||
sourceAddress: sourceAddress, sourcePort: sourcePort);
|
||||
s.destroy();
|
||||
server.close();
|
||||
}
|
||||
|
||||
Future testCustomPortNoSourceAddress(
|
||||
String host, int port, String expectedAddress, int sourcePort) async {
|
||||
Completer completer = new Completer();
|
||||
var server = await ServerSocket.bind(host, port);
|
||||
|
||||
server.listen((client) {
|
||||
Expect.equals(server.port, port);
|
||||
Expect.equals(client.remotePort, sourcePort);
|
||||
Expect.equals(client.address.address, expectedAddress);
|
||||
client.destroy();
|
||||
completer.complete();
|
||||
});
|
||||
|
||||
Socket s = await Socket.connect(host, port, sourcePort: sourcePort);
|
||||
s.destroy();
|
||||
server.close();
|
||||
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
Future testNoCustomPort(String host, int port, String sourceAddress) async {
|
||||
Completer completer = new Completer();
|
||||
var server = await ServerSocket.bind(host, port);
|
||||
Socket.connect(host, port, sourceAddress: sourceAddress).then((clientSocket) {
|
||||
server.listen((client) {
|
||||
Expect.equals(server.port, port);
|
||||
Expect.equals(client.remotePort, clientSocket.port);
|
||||
Expect.equals(client.address.address, sourceAddress);
|
||||
|
||||
client.destroy();
|
||||
completer.complete();
|
||||
});
|
||||
|
||||
clientSocket.destroy();
|
||||
server.close();
|
||||
});
|
||||
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
Future testNoCustomPortNoSourceAddress(
|
||||
String host, int port, String expectedAddress) async {
|
||||
Completer completer = new Completer();
|
||||
var server = await ServerSocket.bind(host, port);
|
||||
Socket.connect(host, port).then((clientSocket) {
|
||||
server.listen((client) {
|
||||
Expect.equals(server.port, port);
|
||||
Expect.equals(client.remotePort, clientSocket.port);
|
||||
Expect.equals(client.address.address, expectedAddress);
|
||||
clientSocket.destroy();
|
||||
client.destroy();
|
||||
server.close();
|
||||
completer.complete();
|
||||
});
|
||||
});
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
Future main() async {
|
||||
await testCustomPortIPv4();
|
||||
await testCustomPortIPv6();
|
||||
|
||||
await testNoCustomPortIPv4();
|
||||
await testNoCustomPortIPv6();
|
||||
|
||||
await testNoCustomPortNoSourceAddressIPv4();
|
||||
await testNoCustomPortNoSourceAddressIPv6();
|
||||
}
|
||||
@@ -161,12 +161,12 @@ class LinkMock extends FileSystemEntity implements Link {
|
||||
}
|
||||
|
||||
Future<Socket> socketConnect(host, int port,
|
||||
{sourceAddress, Duration timeout}) {
|
||||
{sourceAddress, int sourcePort, Duration timeout}) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<ConnectionTask<Socket>> socketStartConnect(host, int port,
|
||||
{sourceAddress}) {
|
||||
{sourceAddress, int sourcePort}) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
// Copyright (c) 2021, 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";
|
||||
|
||||
Future testCustomPortIPv4() async {
|
||||
String clientAddress = "127.0.0.1";
|
||||
int customLocalPort = 50988;
|
||||
String serverAddress = clientAddress;
|
||||
int port = 50989;
|
||||
|
||||
testCustomPort(serverAddress, port, clientAddress, customLocalPort);
|
||||
}
|
||||
|
||||
Future testCustomPortIPv6() async {
|
||||
String clientAddress = "::1";
|
||||
int customLocalPort = 50988;
|
||||
String serverAddress = clientAddress;
|
||||
int port = 50989;
|
||||
|
||||
testCustomPort(serverAddress, port, clientAddress, customLocalPort);
|
||||
}
|
||||
|
||||
Future testCustomPortIPv4NoSourceAddress() async {
|
||||
String expectedClientAddress = "127.0.0.1";
|
||||
int customLocalPort = 50988;
|
||||
String serverAddress = expectedClientAddress;
|
||||
int port = 50989;
|
||||
|
||||
testCustomPort(serverAddress, port, expectedClientAddress, customLocalPort);
|
||||
}
|
||||
|
||||
Future testCustomPortIPv6NoSourceAddress() async {
|
||||
String expectedClientAddress = "::1";
|
||||
int customLocalPort = 50988;
|
||||
String serverAddress = expectedClientAddress;
|
||||
int port = 50989;
|
||||
|
||||
testCustomPort(serverAddress, port, expectedClientAddress, customLocalPort);
|
||||
}
|
||||
|
||||
Future testNoCustomPortIPv4() async {
|
||||
String host = "127.0.0.1";
|
||||
String clientAddress = host;
|
||||
int serverPort = 39998;
|
||||
|
||||
await testNoCustomPortNoSourceAddress(host, serverPort, clientAddress);
|
||||
}
|
||||
|
||||
Future testNoCustomPortIPv6() async {
|
||||
String host = "::1";
|
||||
String clientAddress = host;
|
||||
int serverPort = 39998;
|
||||
|
||||
await testNoCustomPortNoSourceAddress(host, serverPort, clientAddress);
|
||||
}
|
||||
|
||||
Future testNoCustomPortNoSourceAddressIPv4() async {
|
||||
String host = "127.0.0.1";
|
||||
String expectedAddress = host;
|
||||
int serverPort = 39998;
|
||||
|
||||
await testNoCustomPortNoSourceAddress(host, serverPort, expectedAddress);
|
||||
}
|
||||
|
||||
Future testNoCustomPortNoSourceAddressIPv6() async {
|
||||
String host = "::1";
|
||||
String expectedAddress = host;
|
||||
int serverPort = 39998;
|
||||
|
||||
await testNoCustomPortNoSourceAddress(host, serverPort, expectedAddress);
|
||||
}
|
||||
|
||||
// Core functionality
|
||||
void testCustomPort(
|
||||
String host, int port, String sourceAddress, int sourcePort) async {
|
||||
var server = await ServerSocket.bind(host, port);
|
||||
server.listen((client) {
|
||||
Expect.equals(server.port, port);
|
||||
Expect.equals(client.remotePort, sourcePort);
|
||||
Expect.equals(client.address.address, sourceAddress);
|
||||
client.destroy();
|
||||
});
|
||||
|
||||
Socket s = await Socket.connect(host, port,
|
||||
sourceAddress: sourceAddress, sourcePort: sourcePort);
|
||||
s.destroy();
|
||||
server.close();
|
||||
}
|
||||
|
||||
Future testCustomPortNoSourceAddress(
|
||||
String host, int port, String expectedAddress, int sourcePort) async {
|
||||
Completer completer = new Completer();
|
||||
var server = await ServerSocket.bind(host, port);
|
||||
|
||||
server.listen((client) {
|
||||
Expect.equals(server.port, port);
|
||||
Expect.equals(client.remotePort, sourcePort);
|
||||
Expect.equals(client.address.address, expectedAddress);
|
||||
client.destroy();
|
||||
completer.complete();
|
||||
});
|
||||
|
||||
Socket s = await Socket.connect(host, port, sourcePort: sourcePort);
|
||||
s.destroy();
|
||||
server.close();
|
||||
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
Future testNoCustomPort(String host, int port, String sourceAddress) async {
|
||||
Completer completer = new Completer();
|
||||
var server = await ServerSocket.bind(host, port);
|
||||
Socket.connect(host, port, sourceAddress: sourceAddress).then((clientSocket) {
|
||||
server.listen((client) {
|
||||
Expect.equals(server.port, port);
|
||||
Expect.equals(client.remotePort, clientSocket.port);
|
||||
Expect.equals(client.address.address, sourceAddress);
|
||||
|
||||
client.destroy();
|
||||
completer.complete();
|
||||
});
|
||||
|
||||
clientSocket.destroy();
|
||||
server.close();
|
||||
});
|
||||
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
Future testNoCustomPortNoSourceAddress(
|
||||
String host, int port, String expectedAddress) async {
|
||||
Completer completer = new Completer();
|
||||
var server = await ServerSocket.bind(host, port);
|
||||
Socket.connect(host, port).then((clientSocket) {
|
||||
server.listen((client) {
|
||||
Expect.equals(server.port, port);
|
||||
Expect.equals(client.remotePort, clientSocket.port);
|
||||
Expect.equals(client.address.address, expectedAddress);
|
||||
clientSocket.destroy();
|
||||
client.destroy();
|
||||
server.close();
|
||||
completer.complete();
|
||||
});
|
||||
});
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
Future main() async {
|
||||
await testCustomPortIPv4();
|
||||
await testCustomPortIPv6();
|
||||
|
||||
await testNoCustomPortIPv4();
|
||||
await testNoCustomPortIPv6();
|
||||
|
||||
await testNoCustomPortNoSourceAddressIPv4();
|
||||
await testNoCustomPortNoSourceAddressIPv6();
|
||||
}
|
||||
Reference in New Issue
Block a user