// 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";

InternetAddress HOST;
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.readClosed:
        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.readClosed:
        tryComplete();
        break;
    }
  }, onError: (e) {
    Expect.isTrue(e is IOException);
    tryComplete();
  });
  return completer.future;
}

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

Future test(bool hostnameInConnect) {
  return RawServerSocket.bind(HOST, 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);
      }).whenComplete(server.close);
    });
    return connectClient(server.port, hostnameInConnect).then(runClient);
  });
}

main() {
  asyncStart();
  InternetAddress.lookup("localhost").then((hosts) {
    HOST = hosts.first;
    return Future.wait([test(false), test(true)]);
  }).then((_) => asyncEnd());
}
