// Copyright (c) 2015, 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.
//
// OtherResources=certificates/server_chain.pem
// OtherResources=certificates/server_key.pem
// OtherResources=certificates/trusted_certs.pem

// @dart = 2.9

import 'dart:io';
import 'dart:convert';

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

const String NAME_LENGTH_ERROR = 'Length of protocol must be between 1 and 255';

const String MESSAGE_LENGTH_ERROR =
    'The maximum message length supported is 2^13-1';

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

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

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

// Tests that client/server with same protocol can securely establish a
// connection, negotiate the protocol and can send data to each other.
void testSuccessfulAlpnNegotiationConnection(List<String> clientProtocols,
    List<String> serverProtocols, String selectedProtocol) {
  asyncStart();
  var sContext = serverContext()..setAlpnProtocols(serverProtocols, true);
  SecureServerSocket.bind('localhost', 0, sContext)
      .then((SecureServerSocket server) {
    asyncStart();
    server.first.then((SecureSocket socket) {
      Expect.equals(selectedProtocol, socket.selectedProtocol);
      socket
        ..write('server message')
        ..close();
      ascii.decoder.bind(socket).join('').then((String s) {
        Expect.equals('client message', s);
        asyncEnd();
      });
    });

    asyncStart();
    SecureSocket.connect('localhost', server.port,
            context: clientContext(), supportedProtocols: clientProtocols)
        .then((socket) {
      Expect.equals(selectedProtocol, socket.selectedProtocol);
      socket
        ..write('client message')
        ..close();
      ascii.decoder.bind(socket).join('').then((String s) {
        Expect.equals('server message', s);
        server.close();
        asyncEnd();
      });
    });

    asyncEnd();
  });
}

void testInvalidArgument(List<String> protocols, String errorIncludes) {
  testInvalidArgumentServerContext(protocols, errorIncludes);
  testInvalidArgumentClientContext(protocols, errorIncludes);
  testInvalidArgumentClientConnect(protocols, errorIncludes);
}

void testInvalidArgumentServerContext(
    List<String> protocols, String errorIncludes) {
  Expect.throws(() => serverContext().setAlpnProtocols(protocols, true), (e) {
    Expect.isTrue(e is ArgumentError);
    Expect.isTrue(e.toString().contains(errorIncludes));
    return true;
  });
}

void testInvalidArgumentClientContext(
    List<String> protocols, String errorIncludes) {
  Expect.throws(() => clientContext().setAlpnProtocols(protocols, false), (e) {
    Expect.isTrue(e is ArgumentError);
    Expect.isTrue(e.toString().contains(errorIncludes));
    return true;
  });
}

void testInvalidArgumentClientConnect(
    List<String> protocols, String errorIncludes) {
  asyncStart();
  var sContext = serverContext()..setAlpnProtocols(['abc'], true);
  SecureServerSocket.bind('localhost', 0, sContext).then((server) async {
    asyncStart();
    server.listen((SecureSocket socket) {
      Expect.fail(
          "Unexpected connection made to server, with bad client argument");
    }, onError: (e) {
      Expect.fail("Unexpected error on server stream: $e");
    }, onDone: () {
      asyncEnd();
    });

    asyncStart();
    SecureSocket.connect('localhost', server.port,
            context: clientContext(), supportedProtocols: protocols)
        .then((socket) {
      Expect.fail(
          "Unexpected connection made from client, with bad client argument");
    }, onError: (e) {
      Expect.isTrue(e is ArgumentError);
      Expect.isTrue(e.toString().contains(errorIncludes));
      server.close();
      asyncEnd();
    });
    asyncEnd();
  });
}

main() {
  final longname256 = 'p' * 256;
  final String longname255 = 'p' * 255;
  final String strangelongname255 = 'ø' + 'p' * 253;
  final String strangelongname256 = 'ø' + 'p' * 254;

  // This produces a message of (1 << 13) - 2 bytes. 2^12 -1 strings are each
  // encoded by 1 length byte and 1 ascii byte.
  final List<String> manyProtocols =
      new Iterable.generate((1 << 12) - 1, (i) => '0').toList();

  // This produces a message of (1 << 13) bytes. 2^12 strings are each
  // encoded by 1 length byte and 1 ascii byte.
  final List<String> tooManyProtocols =
      new Iterable.generate((1 << 12), (i) => '0').toList();

  // Protocols are in order of decreasing priority. The server will select
  // the first protocol from its list that has a match in the client list.
  // Test successful negotiation, including priority.
  testSuccessfulAlpnNegotiationConnection(['a'], ['a'], 'a');

  testSuccessfulAlpnNegotiationConnection(
      [longname255], [longname255], longname255);

  testSuccessfulAlpnNegotiationConnection(
      [strangelongname255], [strangelongname255], strangelongname255);
  testSuccessfulAlpnNegotiationConnection(manyProtocols, manyProtocols, '0');
  testSuccessfulAlpnNegotiationConnection(
      ['a', 'b', 'c'], ['a', 'b', 'c'], 'a');

  testSuccessfulAlpnNegotiationConnection(['a', 'b', 'c'], ['c'], 'c');

  // Server precedence.
  testSuccessfulAlpnNegotiationConnection(
      ['a', 'b', 'c'], ['c', 'b', 'a'], 'c');

  testSuccessfulAlpnNegotiationConnection(['c'], ['a', 'b', 'c'], 'c');

  testSuccessfulAlpnNegotiationConnection(
      ['s1', 'b', 'e1'], ['s2', 'b', 'e2'], 'b');
  // Test no protocol negotiation support
  testSuccessfulAlpnNegotiationConnection(null, null, null);

  testSuccessfulAlpnNegotiationConnection(['a', 'b', 'c'], null, null);

  testSuccessfulAlpnNegotiationConnection(null, ['a', 'b', 'c'], null);

  testSuccessfulAlpnNegotiationConnection([], [], null);

  testSuccessfulAlpnNegotiationConnection(['a', 'b', 'c'], [], null);

  testSuccessfulAlpnNegotiationConnection([], ['a', 'b', 'c'], null);

  // Test non-overlapping protocols.  The ALPN RFC says the connection
  // should be terminated, but OpenSSL continues as if no ALPN is present.
  // Issue  https://github.com/dart-lang/sdk/issues/23580
  // Chromium issue https://code.google.com/p/chromium/issues/detail?id=497770
  testSuccessfulAlpnNegotiationConnection(['a'], ['b'], null);

  // Test too short / too long protocol names.
  testInvalidArgument([longname256], NAME_LENGTH_ERROR);
  testInvalidArgument([strangelongname256], NAME_LENGTH_ERROR);
  testInvalidArgument([''], NAME_LENGTH_ERROR);
  testInvalidArgument(tooManyProtocols, MESSAGE_LENGTH_ERROR);
}
