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

// @dart = 2.9

import "dart:async";
import "dart:convert";
import "dart:io";
import "dart:typed_data";
import "dart:math";

import "package:async_helper/async_helper.dart";
import "package:crypto/crypto.dart";
import "package:expect/expect.dart";
import "package:path/path.dart";

const WEB_SOCKET_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";

const String HOST_NAME = 'localhost';

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

class SecurityConfiguration {
  final bool secure;

  SecurityConfiguration({bool this.secure});

  Future<HttpServer> createServer({int backlog: 0}) => secure
      ? HttpServer.bindSecure(HOST_NAME, 0, serverContext, backlog: backlog)
      : HttpServer.bind(HOST_NAME, 0, backlog: backlog);

  Future<WebSocket> createClient(int port) =>
      // TODO(whesse): Add client context argument to WebSocket.connect
      WebSocket.connect('${secure ? "wss" : "ws"}://$HOST_NAME:$port/');

  Future<HttpClientResponse> createWebsocket(String url, String headerValue) {
    HttpClient _httpClient = new HttpClient();
    Uri uri = Uri.parse(url);

    Random random = new Random();
    // Generate 16 random bytes.
    Uint8List nonceData = new Uint8List(16);
    for (int i = 0; i < 16; i++) {
      nonceData[i] = random.nextInt(256);
    }
    String nonce = base64.encode(nonceData);

    uri = new Uri(
        scheme: uri.isScheme("wss") ? "https" : "http",
        userInfo: uri.userInfo,
        host: uri.host,
        port: uri.port,
        path: uri.path,
        query: uri.query,
        fragment: uri.fragment);
    return _httpClient.openUrl("GET", uri).then((request) {
      if (uri.userInfo != null && !uri.userInfo.isEmpty) {
        // If the URL contains user information use that for basic
        // authorization.
        String auth = base64.encode(utf8.encode(uri.userInfo));
        request.headers.set(HttpHeaders.authorizationHeader, "Basic $auth");
      }
      // Setup the initial handshake.
      request.headers
        ..set(HttpHeaders.connectionHeader, "Upgrade")
        ..set(HttpHeaders.upgradeHeader, "websocket")
        ..set("Sec-WebSocket-Key", nonce)
        ..set("Cache-Control", "no-cache")
        ..set("Sec-WebSocket-Version", "13")
        ..set("Sec-WebSocket-Extensions", headerValue);

      return request.close();
    });
  }

  void testCompressionSupport(
      {server: false, client: false, contextTakeover: false}) {
    asyncStart();

    var clientOptions = new CompressionOptions(
        enabled: client,
        serverNoContextTakeover: contextTakeover,
        clientNoContextTakeover: contextTakeover);
    var serverOptions = new CompressionOptions(
        enabled: server,
        serverNoContextTakeover: contextTakeover,
        clientNoContextTakeover: contextTakeover);

    createServer().then((server) {
      server.listen((request) {
        Expect.isTrue(WebSocketTransformer.isUpgradeRequest(request));
        WebSocketTransformer.upgrade(request, compression: serverOptions)
            .then((webSocket) {
          webSocket.listen((message) {
            Expect.equals("Hello World", message);

            webSocket.add(message);
            webSocket.close();
          });
          webSocket.add("Hello World");
        });
      });

      var url = '${secure ? "wss" : "ws"}://$HOST_NAME:${server.port}/';
      WebSocket.connect(url, compression: clientOptions).then((websocket) {
        var future = websocket.listen((message) {
          Expect.equals("Hello World", message);
        }).asFuture();
        websocket.add("Hello World");
        return future;
      }).then((_) {
        server.close();
        asyncEnd();
      });
    });
  }

  void testContextSupport(
      {CompressionOptions serverOpts,
      CompressionOptions clientOpts,
      int messages}) {
    asyncStart();

    createServer().then((server) {
      server.listen((request) {
        Expect.isTrue(WebSocketTransformer.isUpgradeRequest(request));
        WebSocketTransformer.upgrade(request, compression: serverOpts)
            .then((webSocket) {
          webSocket.listen((message) {
            Expect.equals("Hello World", message);
            webSocket.add(message);
          });
        });
      });

      var url = '${secure ? "wss" : "ws"}://$HOST_NAME:${server.port}/';
      WebSocket.connect(url, compression: clientOpts).then((websocket) {
        var i = 1;
        websocket.listen((message) {
          Expect.equals("Hello World", message);
          if (i == messages) {
            websocket.close();
            return;
          }
          websocket.add("Hello World");
          i++;
        }, onDone: () {
          server.close();
          asyncEnd();
        });
        websocket.add("Hello World");
      });
    });
  }

  void testCompressionHeaders() {
    asyncStart();
    createServer().then((server) {
      server.listen((request) {
        Expect.equals(
            'Upgrade', request.headers.value(HttpHeaders.connectionHeader));
        Expect.equals(
            'websocket', request.headers.value(HttpHeaders.upgradeHeader));

        var key = request.headers.value('Sec-WebSocket-Key');
        var digest = sha1.convert("$key$WEB_SOCKET_GUID".codeUnits);
        var accept = base64.encode(digest.bytes);
        request.response
          ..statusCode = HttpStatus.switchingProtocols
          ..headers.add(HttpHeaders.connectionHeader, "Upgrade")
          ..headers.add(HttpHeaders.upgradeHeader, "websocket")
          ..headers.add("Sec-WebSocket-Accept", accept)
          ..headers.add(
              "Sec-WebSocket-Extensions",
              "permessage-deflate;"
                  // Test quoted values and space padded =
                  'server_max_window_bits="10"; client_max_window_bits = 12'
                  'client_no_context_takeover; server_no_context_takeover');
        request.response.contentLength = 0;
        request.response.detachSocket().then((socket) {
          return new WebSocket.fromUpgradedSocket(socket, serverSide: true);
        }).then((websocket) {
          websocket.add("Hello");
          websocket.close();
          asyncEnd();
        });
      });

      var url = '${secure ? "wss" : "ws"}://$HOST_NAME:${server.port}/';

      WebSocket.connect(url).then((websocket) {
        return websocket.listen((message) {
          Expect.equals("Hello", message);
          websocket.close();
        }).asFuture();
      }).then((_) => server.close());
    });
  }

  void testReturnHeaders(String headerValue, String expected,
      {CompressionOptions serverCompression:
          CompressionOptions.compressionDefault}) {
    asyncStart();
    createServer().then((server) {
      server.listen((request) {
        // Stuff
        Expect.isTrue(WebSocketTransformer.isUpgradeRequest(request));
        WebSocketTransformer.upgrade(request, compression: serverCompression)
            .then((webSocket) {
          webSocket.listen((message) {
            Expect.equals("Hello World", message);

            webSocket.add(message);
            webSocket.close();
          });
        });
      });

      var url = '${secure ? "wss" : "ws"}://$HOST_NAME:${server.port}/';
      createWebsocket(url, headerValue).then((HttpClientResponse response) {
        Expect.equals(response.statusCode, HttpStatus.switchingProtocols);
        print(response.headers.value('Sec-WebSocket-Extensions'));
        Expect.equals(
            response.headers.value("Sec-WebSocket-Extensions"), expected);

        String accept = response.headers.value("Sec-WebSocket-Accept");
        Expect.isNotNull(accept);

        var protocol = response.headers.value('Sec-WebSocket-Protocol');
        return response.detachSocket().then((socket) =>
            new WebSocket.fromUpgradedSocket(socket,
                protocol: protocol, serverSide: false));
      }).then((websocket) {
        var future = websocket.listen((message) {
          Expect.equals("Hello", message);
          websocket.close();
        }).asFuture();
        websocket.add("Hello World");
        return future;
      }).then((_) {
        server.close();
        asyncEnd();
      });
    }); // End createServer
  }

  void testClientRequestHeaders(CompressionOptions compression) {
    asyncStart();
    createServer().then((server) {
      server.listen((request) {
        var extensionHeader = request.headers.value('Sec-WebSocket-Extensions');
        var hv = HeaderValue.parse(extensionHeader);
        Expect.equals(compression.serverNoContextTakeover,
            hv.parameters.containsKey('server_no_context_takeover'));
        Expect.equals(compression.clientNoContextTakeover,
            hv.parameters.containsKey('client_no_context_takeover'));
        Expect.equals(compression.serverMaxWindowBits?.toString(),
            hv.parameters['server_max_window_bits']);
        Expect.equals(compression.clientMaxWindowBits?.toString(),
            hv.parameters['client_max_window_bits']);

        WebSocketTransformer.upgrade(request).then((webSocket) {
          webSocket.listen((message) {
            Expect.equals('Hello World', message);

            webSocket.add(message);
            webSocket.close();
          });
        });
      });

      var url = '${secure ? "wss" : "ws"}://$HOST_NAME:${server.port}/';

      WebSocket.connect(url, compression: compression).then((websocket) {
        var future = websocket.listen((message) {
          Expect.equals('Hello World', message);
          websocket.close();
        }).asFuture();
        websocket.add('Hello World');
        return future;
      }).then((_) {
        server.close();
        asyncEnd();
      });
    });
  }

  void runTests() {
    // No compression or takeover
    testCompressionSupport();
    // compression no takeover
    testCompressionSupport(server: true, client: true);
    // compression and context takeover.
    testCompressionSupport(server: true, client: true, contextTakeover: true);
    // Compression on client but not server. No take over
    testCompressionSupport(client: true);
    // Compression on server but not client.
    testCompressionSupport(server: true);

    // Test Multiple messages with various context takeover configurations.
    // no context takeover on the server.
    var serverComp = new CompressionOptions(serverNoContextTakeover: true);
    testContextSupport(
        serverOpts: serverComp, clientOpts: serverComp, messages: 5);
    // no contexttakeover on the client.
    var clientComp = new CompressionOptions(clientNoContextTakeover: true);
    testContextSupport(
        serverOpts: clientComp, clientOpts: clientComp, messages: 5);
    // no context takeover enabled for both.
    var compression = new CompressionOptions(
        serverNoContextTakeover: true, clientNoContextTakeover: true);
    testContextSupport(
        serverOpts: compression, clientOpts: compression, messages: 5);
    // no context take over for opposing configurations.
    testContextSupport(
        serverOpts: serverComp, clientOpts: clientComp, messages: 5);
    testContextSupport(
        serverOpts: clientComp, clientOpts: serverComp, messages: 5);

    testCompressionHeaders();
    // Chrome headers
    testReturnHeaders('permessage-deflate; client_max_window_bits',
        "permessage-deflate; client_max_window_bits=15");
    // Firefox headers
    testReturnHeaders(
        'permessage-deflate', "permessage-deflate; client_max_window_bits=15");
    // Ensure max_window_bits resize appropriately.
    testReturnHeaders(
        'permessage-deflate; server_max_window_bits=10',
        "permessage-deflate;"
            " server_max_window_bits=10;"
            " client_max_window_bits=10");
    // Don't provider context takeover if requested but not enabled.
    // Default is not enabled.
    testReturnHeaders(
        'permessage-deflate; client_max_window_bits;'
            'client_no_context_takeover',
        'permessage-deflate; client_max_window_bits=15');
    // Enable context Takeover and provide if requested.
    compression = new CompressionOptions(
        clientNoContextTakeover: true, serverNoContextTakeover: true);
    testReturnHeaders(
        'permessage-deflate; client_max_window_bits; '
            'client_no_context_takeover',
        'permessage-deflate; client_no_context_takeover; '
            'client_max_window_bits=15',
        serverCompression: compression);
    // Enable context takeover and don't provide if not requested
    compression = new CompressionOptions(
        clientNoContextTakeover: true, serverNoContextTakeover: true);
    testReturnHeaders('permessage-deflate; client_max_window_bits; ',
        'permessage-deflate; client_max_window_bits=15',
        serverCompression: compression);

    compression = CompressionOptions.compressionDefault;
    testClientRequestHeaders(compression);
    compression = new CompressionOptions(
        clientNoContextTakeover: true, serverNoContextTakeover: true);
    testClientRequestHeaders(compression);
    compression = new CompressionOptions(
        clientNoContextTakeover: true,
        serverNoContextTakeover: true,
        clientMaxWindowBits: 8,
        serverMaxWindowBits: 8);
    testClientRequestHeaders(compression);
  }
}

main() {
  new SecurityConfiguration(secure: false).runTests();
  // TODO(whesse): Make WebSocket.connect() take an optional context: parameter.
  // new SecurityConfiguration(secure: true).runTests();
}
