// 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.
//
// VMOptions=
// VMOptions=--short_socket_read
// VMOptions=--short_socket_write
// VMOptions=--short_socket_read --short_socket_write

import "dart:async";
import "dart:io";

import "package:async_helper/async_helper.dart";
import "package:expect/expect.dart";

InternetAddress HOST;
String localFile(path) => Platform.script.resolve(path).toFilePath();

SecurityContext serverContext = new SecurityContext()
  ..useCertificateChain(localFile('certificates/server_chain.pem'))
  ..usePrivateKey(localFile('certificates/server_key.pem'),
                  password: 'dartdart');

SecurityContext clientContext = new SecurityContext()
  ..setTrustedCertificates(file: localFile('certificates/trusted_certs.pem'));

// This test creates a server and a client connects. After connecting
// and an optional initial handshake the connection is secured by
// upgrading to a secure connection The client then writes and the
// server echos. When the server has finished its echo it
// half-closes. When the client gets the close event is closes fully.
//
// The test can be run in different configurations based on
// the boolean arguments:
//
// handshakeBeforeSecure
// When this argument is true some initial clear text handshake is done
// between client and server before the connection is secured. This argument
// only makes sense when both listenSecure and connectSecure are false.
//
// postponeSecure
// When this argument is false the securing of the server end will
// happen as soon as the last byte of the handshake before securing
// has been written. When this argument is true the securing of the
// server will not happen until the first TLS handshake data has been
// received from the client. This argument only takes effect when
// handshakeBeforeSecure is true.
void test(bool hostnameInConnect,
          bool handshakeBeforeSecure,
          [bool postponeSecure = false]) {
  asyncStart();

  const messageSize = 1000;
  const handshakeMessageSize = 100;

  List<int> createTestData() {
    List<int> data = new List<int>(messageSize);
    for (int i = 0; i < messageSize; i++) {
      data[i] = i & 0xff;
    }
    return data;
  }

  List<int> createHandshakeTestData() {
    List<int> data = new List<int>(handshakeMessageSize);
    for (int i = 0; i < handshakeMessageSize; i++) {
      data[i] = i & 0xff;
    }
    return data;
  }

  void verifyTestData(List<int> data) {
    Expect.equals(messageSize, data.length);
    List<int> expected = createTestData();
    for (int i = 0; i < messageSize; i++) {
      Expect.equals(expected[i], data[i]);
    }
  }

  void verifyHandshakeTestData(List<int> data) {
    Expect.equals(handshakeMessageSize, data.length);
    List<int> expected = createHandshakeTestData();
    for (int i = 0; i < handshakeMessageSize; i++) {
      Expect.equals(expected[i], data[i]);
    }
  }

  Future runServer(Socket client) {
    var completer = new Completer();
    var dataReceived = [];
    client.listen(
        (data) {
          dataReceived.addAll(data);
          if (dataReceived.length == messageSize) {
            verifyTestData(dataReceived);
            client.add(dataReceived);
            client.close();
          }
        },
        onDone: () => completer.complete(null));
    return completer.future;
  }

  Future<RawSocket> runClient(Socket socket) {
    var completer = new Completer();
    var dataReceived = [];
    socket.listen(
        (data) {
          dataReceived.addAll(data);
        },
        onDone: () {
          Expect.equals(messageSize, dataReceived.length);
          verifyTestData(dataReceived);
          socket.close();
          completer.complete(null);
        });
    socket.add(createTestData());
    return completer.future;
  }

  Future runServerHandshake(Socket client) {
    var completer = new Completer();
    var dataReceived = [];
    var subscription;
    subscription = client.listen(
        (data) {
          if (dataReceived.length == handshakeMessageSize) {
            Expect.isTrue(postponeSecure);
            subscription.pause();
            completer.complete(data);
          }
          dataReceived.addAll(data);
          if (dataReceived.length == handshakeMessageSize) {
            verifyHandshakeTestData(dataReceived);
            client.add(dataReceived);
            if (!postponeSecure) {
              completer.complete(null);
            }
          }
        },
        onDone: () => completer.complete(null));
    return completer.future;
  }

  Future<Socket> runClientHandshake(Socket socket) {
    var completer = new Completer();
    var dataReceived = [];
    socket.listen(
        (data) {
          dataReceived.addAll(data);
          if (dataReceived.length == handshakeMessageSize) {
            verifyHandshakeTestData(dataReceived);
            completer.complete(null);
          }
        },
        onDone: () => Expect.fail("Should not be called")
    );
    socket.add(createHandshakeTestData());
    return completer.future;
  }

  Future<SecureSocket> connectClient(int port) {
    if (!handshakeBeforeSecure) {
      return Socket.connect(HOST, port).then((socket) {
        var future;
        if (hostnameInConnect) {
          future = SecureSocket.secure(socket, context: clientContext);
        } else {
          future = SecureSocket.secure(socket,
                                       host: HOST,
                                       context: clientContext);
        }
        return future.then((secureSocket) {
          socket.add([0]);
          return secureSocket;
        });
      });
    } else {
      return Socket.connect(HOST, port).then((socket) {
        return runClientHandshake(socket).then((_) {
            var future;
            if (hostnameInConnect) {
              future = SecureSocket.secure(socket, context: clientContext);
            } else {
              future = SecureSocket.secure(socket,
                                           host: HOST,
                                           context: clientContext);
            }
            return future.then((secureSocket) {
              socket.add([0]);
              return secureSocket;
            });
        });
      });
    }
  }

  serverReady(server) {
    server.listen((client) {
      if (!handshakeBeforeSecure) {
        SecureSocket.secureServer(client, serverContext).then((secureClient) {
          client.add([0]);
          runServer(secureClient).then((_) => server.close());
        });
      } else {
        runServerHandshake(client).then((carryOverData) {
          SecureSocket.secureServer(
              client,
              serverContext,
              bufferedData: carryOverData).then((secureClient) {
            client.add([0]);
            runServer(secureClient).then((_) => server.close());
          });
        });
      }
    });

    connectClient(server.port).then(runClient).then((socket) {
      asyncEnd();
    });
  }

  ServerSocket.bind(HOST, 0).then(serverReady);
}

main() {
  asyncStart();
  InternetAddress.lookup("localhost").then((hosts) {
    HOST = hosts.first;
    test(false, false);
    // TODO(whesse): Enable the test with all argument combinations:
    //  test(true, false);
    //  test(false, true);
    //  test(true, true);
    //  test(false, true, true);
    //  test(true, true, true);
    asyncEnd();
  });
}
