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

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

Future<SecureServerSocket> startEchoServer() {
  return SecureServerSocket.bind(HOST, 0, serverContext).then((server) {
    server.listen((SecureSocket client) {
      client.fold(<int>[], (message, data) => message..addAll(data)).then(
          (message) {
        client.add(message);
        client.close();
      });
    });
    return server;
  });
}

void checkServerCertificate(X509Certificate serverCert) {
  String serverCertString = serverCert.pem;
  String certFile =
      new File(localFile('certificates/server_chain.pem')).readAsStringSync();
  Expect.isTrue(certFile.contains(serverCertString));

  // Computed with:
  // openssl x509 -noout -sha1 -fingerprint -in certificates/server_chain.pem
  List<int> serverSha1 = <int>[
    0xB3, 0x01, 0xCB, 0x7E, 0x6F, 0xEF, 0xBE, 0xEF, //
    0x75, 0x6D, 0xA8, 0x80, 0x60, 0xA8, 0x5D, 0x6F, //
    0xC4, 0xED, 0xCD, 0x48, //
  ];
  Expect.listEquals(serverSha1, serverCert.sha1);
}

Future testClient(server) {
  return SecureSocket
      .connect(HOST, server.port, context: clientContext)
      .then((socket) {
    checkServerCertificate(socket.peerCertificate);
    socket.write("Hello server.");
    socket.close();
    return socket.fold(<int>[], (message, data) => message..addAll(data)).then(
        (message) {
      Expect.listEquals("Hello server.".codeUnits, message);
      return server;
    });
  });
}

void main() {
  asyncStart();
  InternetAddress
      .lookup("localhost")
      .then((hosts) => HOST = hosts.first)
      .then((_) => startEchoServer())
      .then(testClient)
      .then((server) => server.close())
      .then((_) => asyncEnd());
}
