// 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
// OtherResources=certificates/server_chain.pem
// OtherResources=certificates/server_key.pem
// OtherResources=certificates/trusted_certs.pem

// @dart = 2.9

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();
List<int> readLocalFile(path) => (new File(localFile(path))).readAsBytesSync();

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

SecurityContext clientContext = new SecurityContext()
  ..setTrustedCertificates(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 = <int>[];
    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) {
    Completer<RawSocket> completer = new Completer<RawSocket>();
    var dataReceived = <int>[];
    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) {
        Future<SecureSocket> future;
        if (hostnameInConnect) {
          future = SecureSocket.secure(socket, context: clientContext);
        } else {
          future =
              SecureSocket.secure(socket, host: HOST, context: clientContext);
        }
        return future.then<SecureSocket>((SecureSocket secureSocket) {
          Expect.throws(() {
            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) {
            Expect.throws(() {
              socket.add([0]);
            });
            return secureSocket;
          });
        });
      });
    }
  }

  serverReady(server) {
    server.listen((client) {
      if (!handshakeBeforeSecure) {
        SecureSocket.secureServer(client, serverContext).then((secureClient) {
          Expect.throws(() {
            client.add([0]);
          });
          runServer(secureClient).then((_) => server.close());
        });
      } else {
        runServerHandshake(client).then((carryOverData) {
          SecureSocket
              .secureServer(client, serverContext, bufferedData: carryOverData)
              .then((secureClient) {
            Expect.throws(() {
              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();
  });
}
