populateTransportSettings method

String populateTransportSettings({
  1. required String transport,
  2. required String? headerType,
  3. required String? host,
  4. required String? path,
  5. required String? seed,
  6. required String? quicSecurity,
  7. required String? key,
  8. required String? mode,
  9. required String? serviceName,
  10. String? extra,
})

Populates Xray streamSettings from VLESS URL query parameters.

Returns the transport Host-derived SNI suggestion; an explicit TLS SNI should take precedence. transport selects the network, while the other parameters retain the protocol-specific headers, paths, keys, mode and service name. extra carries XHTTP/HTTPUpgrade JSON settings. Native Core remains responsible for accepting the effective transport.

Implementation

String populateTransportSettings({
  required String transport,
  required String? headerType,
  required String? host,
  required String? path,
  required String? seed,
  required String? quicSecurity,
  required String? key,
  required String? mode,
  required String? serviceName,
  String? extra,
}) {
  String sni = '';
  final normalizedTransport = transport.toLowerCase();
  streamSettingsBuilder.network = normalizedTransport;
  if (normalizedTransport == 'tcp') {
    final tcpHeader = <String, dynamic>{"type": "none", "request": null};
    final tcpSettings = <String, dynamic>{
      "header": tcpHeader,
      "acceptProxyProtocol": null
    };
    streamSettingsBuilder.tcpSettings = tcpSettings;
    if (headerType == 'http') {
      tcpHeader['type'] = 'http';
      if (host != "" || path != "") {
        final request = {
          "path": path == null ? ["/"] : path.split(","),
          "headers": {
            "Host": host == null ? "" : host.split(","),
            "User-Agent": [
              "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
              "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_2 like Mac OS X) AppleWebKit/601.1 (KHTML, like Gecko) CriOS/53.0.2785.109 Mobile/14A456 Safari/601.1.46",
            ],
            "Accept-Encoding": [
              "gzip, deflate",
            ],
            "Connection": [
              "keep-alive",
            ],
            "Pragma": "no-cache",
          },
          "version": "1.1",
          "method": "GET",
        };
        tcpHeader['request'] = request;
        final headers = request['headers'] as Map<String, dynamic>;
        final hosts = headers['Host'] as List;
        sni = hosts.isNotEmpty ? hosts.first as String : sni;
      }
    } else {
      tcpHeader['type'] = 'none';
      sni = host != "" ? host ?? '' : '';
    }
  } else if (normalizedTransport == 'raw') {
    final rawHeader = <String, dynamic>{"type": headerType ?? "none"};
    streamSettingsBuilder.rawSettings = {
      "header": rawHeader,
      "acceptProxyProtocol": null,
    };
    sni = host != "" ? host ?? '' : '';
  } else if (normalizedTransport == 'kcp' || normalizedTransport == 'mkcp') {
    streamSettingsBuilder.network = 'kcp';
    streamSettingsBuilder.kcpSettings = {
      "mtu": 1350,
      "tti": 50,
      "uplinkCapacity": 12,
      "downlinkCapacity": 100,
      "congestion": false,
      "readBufferSize": 1,
      "writeBufferSize": 1,
      "header": {
        "type": headerType ?? "none",
      },
      "seed": (seed == null || seed == '') ? null : seed,
    };
  } else if (normalizedTransport == 'ws' ||
      normalizedTransport == 'websocket') {
    streamSettingsBuilder.network = 'ws';
    final wsHeaders = {"Host": host ?? ""};
    final wsSettings = {
      "path": path ?? ['/'],
      "headers": wsHeaders,
      "maxEarlyData": null,
      "useBrowserForwarding": null,
      "acceptProxyProtocol": null,
    };
    streamSettingsBuilder.wsSettings = wsSettings;
    sni = wsHeaders['Host'] as String;
  } else if (normalizedTransport == 'h2' || normalizedTransport == 'http') {
    streamSettingsBuilder.network = 'h2';
    final h2Settings = {
      "host": host?.split(",") ?? "",
      "path": path ?? ['/'],
    };
    streamSettingsBuilder.h2Settings = h2Settings;
    final hosts = h2Settings['host'];
    sni = hosts is List && hosts.isNotEmpty ? hosts.first as String : sni;
  } else if (normalizedTransport == 'quic') {
    streamSettingsBuilder.quicSettings = {
      "security": quicSecurity ?? 'none',
      "key": key ?? '',
      "header": {"type": headerType ?? "none"},
    };
  } else if (normalizedTransport == 'grpc') {
    streamSettingsBuilder.grpcSettings = {
      "serviceName": serviceName ?? "",
      "multiMode": mode == "multi",
    };
    sni = host ?? "";
  } else if (normalizedTransport == 'xhttp') {
    // XHTTP links often rely on server-specific knobs in `extra`. Preserving
    // them is required for compatibility. Measure an allowed destination
    // through the connected runtime to check the actual network path.
    streamSettingsBuilder.network = 'xhttp';
    final xhttpExtra = decodeXhttpExtra(extra);
    streamSettingsBuilder.xhttpSettings = {
      "host": host ?? "",
      "mode": mode ?? "auto",
      "path": emptyToDefault(path, "/"),
      if (xhttpExtra != null) "extra": xhttpExtra,
    };
    sni = host ?? "";
  } else if (normalizedTransport == 'httpupgrade' ||
      normalizedTransport == 'http_upgrade') {
    streamSettingsBuilder.network = 'httpupgrade';
    final httpupgradeExtra = decodeXhttpExtra(extra);
    streamSettingsBuilder.httpupgradeSettings = {
      "path": emptyToDefault(path, "/"),
      "host": host ?? "",
      "headers": _stringMap(httpupgradeExtra?['headers']),
      "acceptProxyProtocol": null,
    };
    sni = host ?? "";
  }
  return sni;
}