// 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.

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();
      socket.transform(ASCII.decoder).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();
      socket.transform(ASCII.decoder).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);
}
