// 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";
import "package:path/path.dart";

const HOST_NAME = "localhost";
const CERTIFICATE = "localhost_cert";

// This test sends corrupt data in the middle of a secure network connection.
// This tests the error handling of RawSecureSocket.
// A RawSocket connection is upgraded to a secure connection, so that we
// have a reference to the underlying socket.  Then we send some
// unencrypted data on it, in the middle of an encrypted data transfer.


// This test creates a server and then connects a client to the server.
// After connecting, the connection is upgraded to a secure connection.
// The client writes data to the server, then writes unencrypted data
// on the underlying socket.  When the server gets the unencrypted data,
// this causes an error in the NSS code.  When the NSS code is in debug
// mode, bad data on the connection can cause an assertion failure, rather
// than an exception.

const messageSize = 1000;


List<int> createTestData() {
  List<int> data = new List<int>(messageSize);
  for (int i = 0; i < messageSize; 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]);
  }
}


Future runServer(RawSocket client) {
  final completer = new Completer();
  final dataReceived = new List<int>(messageSize);
  int bytesRead = 0;
  client.writeEventsEnabled = false;
  client.listen((event) {
    switch (event) {
      case RawSocketEvent.READ:
        Expect.isTrue(client.available() > 0);
        var buffer = client.read(200);
        dataReceived.setRange(bytesRead, bytesRead + buffer.length, buffer);
        bytesRead += buffer.length;
        if (bytesRead == dataReceived.length) {
          verifyTestData(dataReceived);
        }
        break;
      case RawSocketEvent.WRITE:
        Expect.fail('WRITE event received');
        break;
      case RawSocketEvent.READ_CLOSED:
        Expect.fail('READ_CLOSED event received');
        client.shutdown(SocketDirection.SEND);
        completer.complete(null);
        break;
    }
  },
  onError: (e) {
    Expect.isTrue(e is TlsException);
    Expect.isTrue(e.toString().contains(
        'received a record with an incorrect Message Authentication Code'));
    completer.complete(null);
  });
  return completer.future;
}


Future<RawSocket> runClient(List sockets) {
  final RawSocket baseSocket = sockets[0];
  final RawSecureSocket socket = sockets[1];
  final data = createTestData();
  var completer = new Completer();
  void tryComplete() {
    if (completer != null) {
      completer.complete(null);
      completer = null;
    }
  }

  int bytesWritten = 0;
  socket.listen((event) {
    switch (event) {
      case RawSocketEvent.READ:
        Expect.fail('READ event received');
        break;
      case RawSocketEvent.WRITE:
        if (bytesWritten < data.length) {
          bytesWritten +=  socket.write(data, bytesWritten);
        }
        if (bytesWritten < data.length) {
          socket.writeEventsEnabled = true;
        }
        if (bytesWritten == data.length) {
          baseSocket.write(data, 0, 300);
          socket.shutdown(SocketDirection.SEND);
        }
        break;
      case RawSocketEvent.READ_CLOSED:
        tryComplete();
        break;
    }
  },
  onError: (e) {
    Expect.isTrue(e is IOException);
    tryComplete();
  });
  return completer.future;
}


Future<List> connectClient(int port, bool hostnameInConnect) =>
  RawSocket.connect(HOST_NAME, port)
  .then((socket) =>
    (hostnameInConnect ? RawSecureSocket.secure(socket)
                       : RawSecureSocket.secure(socket, host: HOST_NAME))
    .then((secureSocket) => [socket, secureSocket]));


Future test(bool hostnameInConnect) {
  return RawServerSocket.bind(HOST_NAME, 0).then((server) {
    server.listen((client) {
      RawSecureSocket.secureServer(client, CERTIFICATE)
        .then((secureClient) {
          Expect.throws(() => client.add([0]));
          return runServer(secureClient);
        },
        onError: (e) {
          Expect.isTrue(e is HandshakeException);
          Expect.isTrue(e.toString().contains(
              'received a record with an incorrect Message Authentication'));
        })
        .whenComplete(server.close);
    });
    return connectClient(server.port, hostnameInConnect).then(runClient);
  });
}


main() {
  String certificateDatabase = join(dirname(Platform.script), 'pkcert');
  SecureSocket.initialize(database: certificateDatabase,
                          password: 'dartdart',
                          useBuiltinRoots: false);
  asyncStart();
  Future.wait([test(false), test(true)])
      .then((_) => asyncEnd());
}
