// Copyright (c) 2013, 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 'test_utils.dart' show retry, throws, withTempDir;

Future testArguments(connectFunction) async {
  var sourceAddress;
  final serverIPv4 = await ServerSocket.bind(InternetAddress.loopbackIPv4, 0);
  serverIPv4.listen((_) {
    throw 'Unexpected connection from address $sourceAddress';
  });

  final serverIPv6 = await ServerSocket.bind(InternetAddress.loopbackIPv6, 0);
  serverIPv6.listen((_) {
    throw 'Unexpected connection from address $sourceAddress';
  });

  // Illegal type for sourceAddress.
  for (sourceAddress in ['www.google.com', 'abc']) {
    await throws(
      () => connectFunction(
        '127.0.0.1',
        serverIPv4.port,
        sourceAddress: sourceAddress,
      ),
      (e) => e is ArgumentError,
    );
  }
  // Unsupported local address.
  for (sourceAddress in ['8.8.8.8', new InternetAddress('8.8.8.8')]) {
    await throws(
      () => connectFunction(
        '127.0.0.1',
        serverIPv4.port,
        sourceAddress: sourceAddress,
      ),
      (e) =>
          e is SocketException && e.address == new InternetAddress('8.8.8.8'),
    );
  }
  // Address family mismatch for IPv4.
  for (sourceAddress in [
    '::1',
    InternetAddress.loopbackIPv6,
    InternetAddress('sock', type: InternetAddressType.unix),
  ]) {
    await throws(
      () => connectFunction(
        '127.0.0.1',
        serverIPv4.port,
        sourceAddress: sourceAddress,
      ),
      (e) => e is SocketException,
    );
  }
  // Address family mismatch for IPv6.
  for (sourceAddress in [
    '127.0.0.1',
    InternetAddress.loopbackIPv4,
    InternetAddress('sock', type: InternetAddressType.unix),
  ]) {
    await throws(
      () =>
          connectFunction('::1', serverIPv6.port, sourceAddress: sourceAddress),
      (e) => e is SocketException,
    );
  }

  await serverIPv4.close();
  await serverIPv6.close();
}

Future testUnixDomainArguments(connectFunction, String socketDir) async {
  var sourceAddress;
  final serverUnix = await ServerSocket.bind(
    InternetAddress('$socketDir/sock', type: InternetAddressType.unix),
    0,
  );
  serverUnix.listen((_) {
    throw 'Unexpected connection from address $sourceAddress';
  });

  // Address family mismatch for Unix domain sockets.
  for (sourceAddress in [
    '127.0.0.1',
    InternetAddress.loopbackIPv4,
    '::1',
    InternetAddress.loopbackIPv6,
  ]) {
    await throws(
      () => connectFunction(
        InternetAddress("$socketDir/sock", type: InternetAddressType.unix),
        serverUnix.port,
        sourceAddress: sourceAddress,
      ),
      (e) =>
          e is SocketException &&
          e.toString().contains('Address family not supported'),
    );
  }
  await serverUnix.close();
}

// IPv4 addresses to use as source address when connecting locally.
var ipV4SourceAddresses = [
  InternetAddress.loopbackIPv4,
  InternetAddress.anyIPv4,
  '127.0.0.1',
  '0.0.0.0',
];

// IPv6 addresses to use as source address when connecting locally.
var ipV6SourceAddresses = [
  InternetAddress.loopbackIPv6,
  InternetAddress.anyIPv6,
  '::1',
  '::',
];

Future testConnect(
  InternetAddress bindAddress,
  bool v6Only,
  Function connectFunction,
  Function closeDestroyFunction,
) async {
  var successCount = 0;
  if (!v6Only) successCount += ipV4SourceAddresses.length;
  if (bindAddress.type == InternetAddressType.IPv6) {
    successCount += ipV6SourceAddresses.length;
  }
  var count = 0;
  var allConnected = new Completer();
  if (successCount == 0) allConnected.complete();

  var server = await ServerSocket.bind(bindAddress, 0, v6Only: v6Only);
  server.listen((s) {
    s.destroy();
    count++;
    if (count == successCount) allConnected.complete();
  });

  // Connect with IPv4 source addresses.
  for (var sourceAddress in ipV4SourceAddresses) {
    if (!v6Only) {
      var s = await connectFunction(
        InternetAddress.loopbackIPv4,
        server.port,
        sourceAddress: sourceAddress,
      );
      closeDestroyFunction(s);
    } else {
      // Cannot use an IPv4 source address to connect to IPv6 if
      // v6Only is specified.
      await throws(
        () => connectFunction(
          InternetAddress.loopbackIPv6,
          server.port,
          sourceAddress: sourceAddress,
        ),
        (e) => e is SocketException,
      );
    }
  }

  // Connect with IPv6 source addresses.
  for (var sourceAddress in ipV6SourceAddresses) {
    if (bindAddress.type == InternetAddressType.IPv6) {
      var s = await connectFunction(
        InternetAddress.loopbackIPv6,
        server.port,
        sourceAddress: sourceAddress,
      );
      closeDestroyFunction(s);
    } else {
      // Cannot use an IPv6 source address to connect to IPv4.
      await throws(
        () => connectFunction(
          InternetAddress.loopbackIPv4,
          server.port,
          sourceAddress: sourceAddress,
        ),
        (e) => e is SocketException,
      );
    }
  }

  await allConnected.future;
  await server.close();
}

main() async {
  await retry(() async {
    await testArguments(RawSocket.connect);
  });
  await retry(() async {
    await testArguments(Socket.connect);
  });

  if (Platform.isMacOS || Platform.isLinux || Platform.isAndroid) {
    await retry(() async {
      await withTempDir('unix_socket_test', (Directory dir) async {
        await testUnixDomainArguments(RawSocket.connect, "${dir.path}");
      });
    });
    await retry(() async {
      await withTempDir('unix_socket_test', (Directory dir) async {
        await testUnixDomainArguments(Socket.connect, "${dir.path}");
      });
    });
  }
  await retry(() async {
    await testConnect(
      InternetAddress.anyIPv4,
      false,
      RawSocket.connect,
      (s) => s.close(),
    );
  });
  await retry(() async {
    await testConnect(
      InternetAddress.anyIPv4,
      false,
      Socket.connect,
      (s) => s.destroy(),
    );
  });
  await retry(() async {
    await testConnect(
      InternetAddress.anyIPv6,
      false,
      RawSocket.connect,
      (s) => s.close(),
    );
  });
  await retry(() async {
    await testConnect(
      InternetAddress.anyIPv6,
      false,
      Socket.connect,
      (s) => s.destroy(),
    );
  });
  await retry(() async {
    await testConnect(
      InternetAddress.anyIPv6,
      true,
      RawSocket.connect,
      (s) => s.close(),
    );
  });
  await retry(() async {
    await testConnect(
      InternetAddress.anyIPv6,
      true,
      Socket.connect,
      (s) => s.destroy(),
    );
  });
}
