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

part of vmservice_io;

// TODO(48602): deprecate SILENT_OBSERVATORY in favor of SILENT_VM_SERVICE
bool silentObservatory = bool.fromEnvironment('SILENT_OBSERVATORY');
bool silentVMService = bool.fromEnvironment('SILENT_VM_SERVICE');

void serverPrint(String s) {
  if (silentObservatory || silentVMService) {
    // We've been requested to be silent.
    return;
  }
  print(s);
}

class WebSocketClient extends Client {
  static const int parseErrorCode = 4000;
  static const int binaryMessageErrorCode = 4001;
  static const int notMapErrorCode = 4002;
  static const int idErrorCode = 4003;
  final WebSocket socket;

  WebSocketClient(this.socket, VMService service) : super(service) {
    socket.listen((message) => onWebSocketMessage(message));
    socket.done.then((_) => close());
  }

  Future<void> disconnect() async {
    if (socket != null) {
      await socket.close();
    }
  }

  void onWebSocketMessage(message) {
    if (message is String) {
      Map map;
      try {
        map = json.decode(message);
      } catch (e) {
        socket.close(parseErrorCode, 'Message parse error: $e');
        return;
      }
      if (map is! Map) {
        socket.close(notMapErrorCode, 'Message must be a JSON map.');
        return;
      }
      try {
        final rpc = Message.fromJsonRpc(this, map);
        switch (rpc.type) {
          case MessageType.Request:
            onRequest(rpc);
            break;
          case MessageType.Notification:
            onNotification(rpc);
            break;
          case MessageType.Response:
            onResponse(rpc);
            break;
        }
      } on dynamic catch (e) {
        socket.close(idErrorCode, e.message);
      }
    } else {
      socket.close(binaryMessageErrorCode, 'Message must be a string.');
    }
  }

  void post(Response? result) {
    if (result == null) {
      // The result of a notification event. Do nothing.
      return;
    }
    try {
      switch (result.kind) {
        case ResponsePayloadKind.String:
        case ResponsePayloadKind.Binary:
          socket.add(result.payload);
          break;
        case ResponsePayloadKind.Utf8String:
          socket.addUtf8Text(result.payload);
          break;
      }
    } on StateError catch (_) {
      // VM has shutdown, do nothing.
      return;
    }
  }

  Map<String, dynamic> toJson() => {
        ...super.toJson(),
        'type': 'WebSocketClient',
        'socket': '$socket',
      };
}

class HttpRequestClient extends Client {
  static final jsonContentType =
      ContentType('application', 'json', charset: 'utf-8');
  final HttpRequest request;

  HttpRequestClient(this.request, VMService service)
      : super(service, sendEvents: false);

  Future<void> disconnect() async {
    await request.response.close();
    close();
  }

  void post(Response? result) {
    if (result == null) {
      // The result of a notification event. Nothing to do other than close the
      // connection.
      close();
      return;
    }

    HttpResponse response = request.response;
    // We closed the connection for bad origins earlier.
    response.headers.add('Access-Control-Allow-Origin', '*');
    response.headers.contentType = jsonContentType;
    switch (result.kind) {
      case ResponsePayloadKind.String:
        response.write(result.payload);
        break;
      case ResponsePayloadKind.Utf8String:
        response.add(result.payload);
        break;
      case ResponsePayloadKind.Binary:
        throw 'Can not handle binary responses';
    }
    response.close();
    close();
  }

  Map<String, dynamic> toJson() {
    final map = super.toJson();
    map['type'] = 'HttpRequestClient';
    map['request'] = '$request';
    return map;
  }
}

class Server {
  static const WEBSOCKET_PATH = '/ws';
  static const ROOT_REDIRECT_PATH = '/index.html';

  final VMService _service;
  final String _ip;
  final bool _originCheckDisabled;
  final bool _authCodesDisabled;
  final bool _enableServicePortFallback;
  final String? _serviceInfoFilename;
  HttpServer? _server;
  bool get running => _server != null;
  bool acceptNewWebSocketConnections = true;
  int _port = -1;

  /// Returns the server address including the auth token.
  Uri? get serverAddress {
    if (!running || _service.isExiting) {
      return null;
    }
    // If DDS is connected it should be treated as the "true" VM service and be
    // advertised as such.
    if (_service.ddsUri != null) {
      return _service.ddsUri;
    }
    final server = _server!;
    final ip = server.address.address;
    final port = server.port;
    final path = !_authCodesDisabled ? '$serviceAuthToken/' : '/';
    return Uri(scheme: 'http', host: ip, port: port, path: path);
  }

  // On Fuchsia, authentication codes are disabled by default. To enable, the authentication token
  // would have to be written into the hub alongside the port number.
  Server(
      this._service,
      this._ip,
      this._port,
      this._originCheckDisabled,
      bool authCodesDisabled,
      this._serviceInfoFilename,
      this._enableServicePortFallback)
      : _authCodesDisabled = (authCodesDisabled || Platform.isFuchsia);

  bool _isAllowedOrigin(String origin) {
    Uri uri;
    try {
      uri = Uri.parse(origin);
    } catch (_) {
      return false;
    }

    // Explicitly add localhost and 127.0.0.1 on any port (necessary for
    // adb port forwarding).
    if ((uri.host == 'localhost') ||
        (uri.host == '::1') ||
        (uri.host == '127.0.0.1')) {
      return true;
    }

    final server = _server!;
    if ((uri.port == server.port) &&
        ((uri.host == server.address.address) ||
            (uri.host == server.address.host))) {
      return true;
    }

    return false;
  }

  bool _originCheck(HttpRequest request) {
    if (_originCheckDisabled) {
      // Always allow.
      return true;
    }
    // First check the web-socket specific origin.
    List<String>? origins = request.headers['Sec-WebSocket-Origin'];
    if (origins == null) {
      // Fall back to the general Origin field.
      origins = request.headers['Origin'];
    }
    if (origins == null) {
      // No origin sent. This is a non-browser client or a same-origin request.
      return true;
    }
    for (final origin in origins) {
      if (_isAllowedOrigin(origin)) {
        return true;
      }
    }
    return false;
  }

  /// Checks the [requestUri] for the service auth token and returns the path
  /// as a String. If the service auth token check fails, returns null.
  /// Returns a Uri if a redirect is required.
  dynamic _checkAuthTokenAndGetPath(Uri requestUri) {
    if (_authCodesDisabled) {
      return requestUri.path == '/' ? ROOT_REDIRECT_PATH : requestUri.path;
    }
    final List<String> requestPathSegments = requestUri.pathSegments;
    if (requestPathSegments.isEmpty) {
      // Malformed.
      return null;
    }
    // Check that we were given the auth token.
    final authToken = requestPathSegments[0];
    if (authToken != serviceAuthToken) {
      // Malformed.
      return null;
    }
    // Missing a trailing '/'. We'll need to redirect to serve
    // ROOT_REDIRECT_PATH correctly, otherwise the response is misinterpreted.
    if (requestPathSegments.length == 1) {
      // requestPathSegments is unmodifiable. Copy it.
      final pathSegments = List<String>.from(requestPathSegments);

      // Adding an empty string to the path segments results in the path having
      // a trailing '/'.
      pathSegments.add('');

      return requestUri.replace(pathSegments: pathSegments);
    }
    // Construct the actual request path by chopping off the auth token.
    return (requestPathSegments[1] == '')
        ? ROOT_REDIRECT_PATH
        : '/${requestPathSegments.sublist(1).join('/')}';
  }

  Future _requestHandler(HttpRequest request) async {
    if (!_originCheck(request)) {
      // This is a cross origin attempt to connect
      request.response.statusCode = HttpStatus.forbidden;
      request.response.write('forbidden origin');
      request.response.close();
      return;
    }
    if (request.method == 'PUT') {
      // PUT requests are forwarded to DevFS for processing.

      List fsNameList;
      List? fsPathList;
      List? fsPathBase64List;
      List? fsUriBase64List;
      Object? fsName;
      Object? fsPath;
      Uri? fsUri;

      try {
        // Extract the fs name and fs path from the request headers.
        fsNameList = request.headers['dev_fs_name']!;
        fsName = fsNameList[0];

        // Prefer Uri encoding first.
        fsUriBase64List = request.headers['dev_fs_uri_b64'];
        if ((fsUriBase64List != null) && (fsUriBase64List.length > 0)) {
          final decodedFsUri = utf8.decode(base64.decode(fsUriBase64List[0]));
          fsUri = Uri.parse(decodedFsUri);
        }

        // Fallback to path encoding.
        if (fsUri == null) {
          fsPathList = request.headers['dev_fs_path'];
          fsPathBase64List = request.headers['dev_fs_path_b64'];
          // If the 'dev_fs_path_b64' header field was sent, use that instead.
          if ((fsPathBase64List != null) && fsPathBase64List.isNotEmpty) {
            fsPath = utf8.decode(base64.decode(fsPathBase64List[0]));
          } else if (fsPathList != null && fsPathList.isNotEmpty) {
            fsPath = fsPathList[0];
          }
        }
      } catch (e) {/* ignore */}

      String result;
      try {
        result = await _service.devfs.handlePutStream(fsName, fsPath, fsUri,
            request.cast<List<int>>().transform(gzip.decoder));
      } catch (e) {
        request.response.statusCode = HttpStatus.internalServerError;
        request.response.write(e);
        request.response.close();
        return;
      }

      if (result != null) {
        request.response.headers.contentType =
            HttpRequestClient.jsonContentType;
        request.response.write(result);
      }
      request.response.close();
      return;
    }
    if (request.method != 'GET') {
      // Not a GET request. Do nothing.
      request.response.statusCode = HttpStatus.methodNotAllowed;
      request.response.write('method not allowed');
      request.response.close();
      return;
    }

    final result = _checkAuthTokenAndGetPath(request.uri);
    if (result == null) {
      // Either no authentication code was provided when one was expected or an
      // incorrect authentication code was provided.
      request.response.statusCode = HttpStatus.forbidden;
      request.response.write('missing or invalid authentication code');
      request.response.close();
      return;
    } else if (result is Uri) {
      // The URI contains the valid auth token but is missing a trailing '/'.
      // Redirect to the same URI with the trailing '/' to correctly serve
      // index.html.
      request.response.redirect(result);
      return;
    }

    final String path = result;
    if (path == WEBSOCKET_PATH) {
      final subprotocols = request.headers['sec-websocket-protocol'];
      if (acceptNewWebSocketConnections) {
        WebSocketTransformer.upgrade(request,
                protocolSelector:
                    subprotocols == null ? null : (_) => 'implicit-redirect',
                compression: CompressionOptions.compressionOff)
            .then((WebSocket webSocket) {
          WebSocketClient(webSocket, _service);
        });
      } else {
        // Attempt to redirect client to the DDS instance.
        request.response.redirect(_service.ddsUri!);
      }
      return;
    }

    if (assets == null) {
      request.response.headers.contentType = ContentType.text;
      request.response.write('This VM was built without the Observatory UI.');
      request.response.close();
      return;
    }
    final asset = assets[path];
    if (asset != null) {
      // Serving up a static asset (e.g. .css, .html, .png).
      request.response.headers.contentType = ContentType.parse(asset.mimeType);
      request.response.add(asset.data);
      request.response.close();
      return;
    }
    // HTTP based service request.
    final client = HttpRequestClient(request, _service);
    final message = Message.fromUri(
        client, Uri(path: path, queryParameters: request.uri.queryParameters));
    client.onRequest(message); // exception free, no need to try catch
  }

  Future<void> _dumpServiceInfoToFile(String serviceInfoFilenameLocal) async {
    final serviceInfo = <String, dynamic>{
      'uri': serverAddress.toString(),
    };
    final file = File.fromUri(Uri.parse(serviceInfoFilenameLocal));
    return file.writeAsString(json.encode(serviceInfo)) as Future<void>;
  }

  Future<Server> startup() async {
    if (_server != null) {
      // Already running.
      return this;
    }
    // Startup HTTP server.
    Future<bool> startServer() async {
      try {
        var address;
        var addresses = await InternetAddress.lookup(_ip);
        // Prefer IPv4 addresses.
        for (int i = 0; i < addresses.length; i++) {
          address = addresses[i];
          if (address.type == InternetAddressType.IPv4) break;
        }
        _server = await HttpServer.bind(address, _port);
      } catch (e, st) {
        if (_port != 0 && _enableServicePortFallback) {
          serverPrint(
              'Failed to bind Dart VM service HTTP server to port $_port. '
              'Falling back to automatic port selection');
          _port = 0;
          return await startServer();
        } else {
          serverPrint('Could not start Dart VM service HTTP server:\n'
              '$e\n$st');
          _notifyServerState('');
          onServerAddressChange(null);
          return false;
        }
      }
      return true;
    }

    if (!(await startServer())) {
      return this;
    }
    if (_service.isExiting) {
      serverPrint('Dart VM service HTTP server exiting before listening as '
          'vm service has received exit request\n');
      await shutdown(true);
      return this;
    }
    final server = _server!;
    server.listen(_requestHandler, cancelOnError: true);
    if (!_waitForDdsToAdvertiseService) {
      await outputConnectionInformation();
    }
    // Server is up and running.
    _notifyServerState(serverAddress.toString());
    onServerAddressChange('$serverAddress');
    return this;
  }

  Future<void> outputConnectionInformation() async {
    serverPrint('The Dart VM service is listening on $serverAddress');
    if (Platform.isFuchsia) {
      // Create a file with the port number.
      final tmp = Directory.systemTemp.path;
      final path = '$tmp/dart.services/${_server!.port}';
      serverPrint('Creating $path');
      File(path)..createSync(recursive: true);
    }
    final serviceInfoFilenameLocal = _serviceInfoFilename;
    if (serviceInfoFilenameLocal != null &&
        serviceInfoFilenameLocal.isNotEmpty) {
      await _dumpServiceInfoToFile(serviceInfoFilenameLocal);
    }
  }

  Future<void> cleanup(bool force) {
    final serverLocal = _server;
    if (serverLocal == null) {
      return Future.value();
    }
    if (Platform.isFuchsia) {
      // Remove the file with the port number.
      final tmp = Directory.systemTemp.path;
      final path = '$tmp/dart.services/${serverLocal.port}';
      serverPrint('Deleting $path');
      File(path)..deleteSync();
    }
    return serverLocal.close(force: force);
  }

  Future<Server> shutdown(bool forced) {
    if (_server == null) {
      // Not started.
      return Future.value(this);
    }

    // Shutdown HTTP server and subscription.
    Uri oldServerAddress = serverAddress!;
    return cleanup(forced).then((_) {
      serverPrint('Dart VM service no longer listening on $oldServerAddress');
      _server = null;
      _notifyServerState('');
      onServerAddressChange(null);
      return this;
    }).catchError((e, st) {
      _server = null;
      serverPrint('Could not shutdown Dart VM service HTTP server:\n$e\n$st\n');
      _notifyServerState('');
      onServerAddressChange(null);
      return this;
    });
  }
}

@pragma("vm:external-name", "VMServiceIO_NotifyServerState")
external void _notifyServerState(String uri);
