// 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 "package:async_helper/async_helper.dart";
import "package:expect/expect.dart";

import 'test_utils.dart' show freeIPv4AndIPv6Port, retry;

Future throws(Function f, Function check) async {
  try {
    await f();
    Expect.fail('Did not throw');
  } catch (e) {
    if (check != null) {
      if (!check(e)) {
        Expect.fail('Unexpected: $e');
      }
    }
  }
}

Future testArguments(connectFunction) async {
  int freePort = await freeIPv4AndIPv6Port();

  var sourceAddress;
  asyncStart();
  var server =
      await ServerSocket.bind(InternetAddress.loopbackIPv4, freePort);
  server.listen((_) {
    throw 'Unexpected connection from address $sourceAddress';
  }, onDone: () => asyncEnd());

  asyncStart();
  // Illegal type for sourceAddress.
  for (sourceAddress in ['www.google.com', 'abc']) {
    await throws(() => connectFunction('127.0.0.1', server.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', server.port,
            sourceAddress: sourceAddress),
        (e) =>
            e is SocketException &&
            e.address == new InternetAddress('8.8.8.8'));
  }
  // Address family mismatch.
  for (sourceAddress in ['::1', InternetAddress.loopbackIPv6]) {
    await throws(
        () => connectFunction('127.0.0.1', server.port,
            sourceAddress: sourceAddress),
        (e) => e is SocketException);
  }
  asyncEnd();
  server.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 {
  int freePort = await freeIPv4AndIPv6Port();

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

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

  asyncStart();

  // Connect with IPv4 source addesses.
  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 addesses.
  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();
  asyncEnd();
}

main() async {
  asyncStart();

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

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

  asyncEnd();
}
