// 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: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(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.scheme == "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.compressionDefault,
      CompressionOptions clientOpts: CompressionOptions.compressionDefault,
      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")!;

        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(false).runTests();
  // TODO(whesse): Make WebSocket.connect() take an optional context: parameter.
  // new SecurityConfiguration(true).runTests();
}
