// 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());
  });
}
