Change mapping and bug fixes

This commit is contained in:
problematicconsumer
2024-02-15 19:39:35 +03:30
parent bd4c5eed7e
commit 702c59c3bc
21 changed files with 501 additions and 422 deletions

View File

@@ -1,19 +1,24 @@
import 'dart:io';
import 'package:dart_mappable/dart_mappable.dart';
import 'package:hiddify/core/localization/translations.dart';
import 'package:hiddify/utils/platform_utils.dart';
import 'package:json_annotation/json_annotation.dart';
@JsonEnum(valueField: 'key')
part 'singbox_config_enum.mapper.dart';
@MappableEnum()
enum ServiceMode {
proxy("proxy"),
systemProxy("system-proxy"),
tun("vpn"),
tunService("vpn-service");
@MappableValue("proxy")
proxy,
const ServiceMode(this.key);
@MappableValue("system-proxy")
systemProxy,
final String key;
@MappableValue("vpn")
tun,
@MappableValue("vpn-service")
tunService;
static ServiceMode get defaultMode =>
PlatformUtils.isDesktop ? systemProxy : tun;
@@ -39,16 +44,19 @@ enum ServiceMode {
};
}
@JsonEnum(valueField: 'key')
@MappableEnum()
enum IPv6Mode {
disable("ipv4_only"),
enable("prefer_ipv4"),
prefer("prefer_ipv6"),
only("ipv6_only");
@MappableValue("ipv4_only")
disable,
const IPv6Mode(this.key);
@MappableValue("prefer_ipv4")
enable,
final String key;
@MappableValue("prefer_ipv6")
prefer,
@MappableValue("ipv6_only")
only;
String present(TranslationsEn t) => switch (this) {
disable => t.settings.config.ipv6Modes.disable,
@@ -58,12 +66,21 @@ enum IPv6Mode {
};
}
@JsonEnum(valueField: 'key')
@MappableEnum()
enum DomainStrategy {
@MappableValue("")
auto(""),
@MappableValue("prefer_ipv6")
preferIpv6("prefer_ipv6"),
@MappableValue("prefer_ipv4")
preferIpv4("prefer_ipv4"),
@MappableValue("ipv4_only")
ipv4Only("ipv4_only"),
@MappableValue("ipv6_only")
ipv6Only("ipv6_only");
const DomainStrategy(this.key);
@@ -76,18 +93,21 @@ enum DomainStrategy {
};
}
@MappableEnum()
enum TunImplementation {
mixed,
system,
gVisor;
}
@MappableEnum()
enum MuxProtocol {
h2mux,
smux,
yamux;
}
@MappableEnum()
enum WarpDetourMode {
outbound,
inbound;

View File

@@ -1,86 +1,127 @@
import 'dart:convert';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:hiddify/core/model/range.dart';
import 'package:dart_mappable/dart_mappable.dart';
import 'package:hiddify/core/model/optional_range.dart';
import 'package:hiddify/features/log/model/log_level.dart';
import 'package:hiddify/singbox/model/singbox_config_enum.dart';
import 'package:hiddify/singbox/model/singbox_rule.dart';
part 'singbox_config_option.freezed.dart';
part 'singbox_config_option.g.dart';
part 'singbox_config_option.mapper.dart';
@freezed
class SingboxConfigOption with _$SingboxConfigOption {
const SingboxConfigOption._();
@MappableClass(
caseStyle: CaseStyle.paramCase,
includeCustomMappers: [
OptionalRangeJsonMapper(),
IntervalMapper(),
],
)
class SingboxConfigOption with SingboxConfigOptionMappable {
const SingboxConfigOption({
required this.executeConfigAsIs,
required this.logLevel,
required this.resolveDestination,
required this.ipv6Mode,
required this.remoteDnsAddress,
required this.remoteDnsDomainStrategy,
required this.directDnsAddress,
required this.directDnsDomainStrategy,
required this.mixedPort,
required this.localDnsPort,
required this.tunImplementation,
required this.mtu,
required this.strictRoute,
required this.connectionTestUrl,
required this.urlTestInterval,
required this.enableClashApi,
required this.clashApiPort,
required this.enableTun,
required this.enableTunService,
required this.setSystemProxy,
required this.bypassLan,
required this.allowConnectionFromLan,
required this.enableFakeDns,
required this.enableDnsRouting,
required this.independentDnsCache,
required this.enableTlsFragment,
required this.tlsFragmentSize,
required this.tlsFragmentSleep,
required this.enableTlsMixedSniCase,
required this.enableTlsPadding,
required this.tlsPaddingSize,
required this.enableMux,
required this.muxPadding,
required this.muxMaxStreams,
required this.muxProtocol,
required this.enableWarp,
required this.warpDetourMode,
required this.warpLicenseKey,
required this.warpCleanIp,
required this.warpPort,
required this.warpNoise,
required this.geoipPath,
required this.geositePath,
required this.rules,
});
@JsonSerializable(fieldRename: FieldRename.kebab)
const factory SingboxConfigOption({
required bool executeConfigAsIs,
required LogLevel logLevel,
required bool resolveDestination,
required IPv6Mode ipv6Mode,
required String remoteDnsAddress,
required DomainStrategy remoteDnsDomainStrategy,
required String directDnsAddress,
required DomainStrategy directDnsDomainStrategy,
required int mixedPort,
required int localDnsPort,
required TunImplementation tunImplementation,
required int mtu,
required bool strictRoute,
required String connectionTestUrl,
@IntervalConverter() required Duration urlTestInterval,
required bool enableClashApi,
required int clashApiPort,
required bool enableTun,
required bool enableTunService,
required bool setSystemProxy,
required bool bypassLan,
required bool allowConnectionFromLan,
required bool enableFakeDns,
required bool enableDnsRouting,
required bool independentDnsCache,
required bool enableTlsFragment,
@RangeWithOptionalCeilJsonConverter()
required RangeWithOptionalCeil tlsFragmentSize,
@RangeWithOptionalCeilJsonConverter()
required RangeWithOptionalCeil tlsFragmentSleep,
required bool enableTlsMixedSniCase,
required bool enableTlsPadding,
@RangeWithOptionalCeilJsonConverter()
required RangeWithOptionalCeil tlsPaddingSize,
required bool enableMux,
required bool muxPadding,
required int muxMaxStreams,
required MuxProtocol muxProtocol,
required bool enableWarp,
required WarpDetourMode warpDetourMode,
required String warpLicenseKey,
required String warpCleanIp,
required int warpPort,
@RangeWithOptionalCeilJsonConverter()
required RangeWithOptionalCeil warpNoise,
required String geoipPath,
required String geositePath,
required List<SingboxRule> rules,
}) = _SingboxConfigOption;
final bool executeConfigAsIs;
final LogLevel logLevel;
final bool resolveDestination;
@MappableField(key: "ipv6-mode")
final IPv6Mode ipv6Mode;
final String remoteDnsAddress;
final DomainStrategy remoteDnsDomainStrategy;
final String directDnsAddress;
final DomainStrategy directDnsDomainStrategy;
final int mixedPort;
final int localDnsPort;
final TunImplementation tunImplementation;
final int mtu;
final bool strictRoute;
final String connectionTestUrl;
final Duration urlTestInterval;
final bool enableClashApi;
final int clashApiPort;
final bool enableTun;
final bool enableTunService;
final bool setSystemProxy;
final bool bypassLan;
final bool allowConnectionFromLan;
final bool enableFakeDns;
final bool enableDnsRouting;
final bool independentDnsCache;
final bool enableTlsFragment;
final OptionalRange tlsFragmentSize;
final OptionalRange tlsFragmentSleep;
final bool enableTlsMixedSniCase;
final bool enableTlsPadding;
final OptionalRange tlsPaddingSize;
final bool enableMux;
final bool muxPadding;
final int muxMaxStreams;
final MuxProtocol muxProtocol;
final bool enableWarp;
final WarpDetourMode warpDetourMode;
final String warpLicenseKey;
final String warpCleanIp;
final int warpPort;
final OptionalRange warpNoise;
final String geoipPath;
final String geositePath;
final List<SingboxRule> rules;
String format() {
const encoder = JsonEncoder.withIndent(' ');
return encoder.convert(toJson());
return encoder.convert(toMap());
}
factory SingboxConfigOption.fromJson(Map<String, dynamic> json) =>
_$SingboxConfigOptionFromJson(json);
}
class IntervalConverter implements JsonConverter<Duration, String> {
const IntervalConverter();
class IntervalMapper extends SimpleMapper<Duration> {
const IntervalMapper();
@override
Duration fromJson(String json) =>
Duration(minutes: int.parse(json.replaceAll("m", "")));
Duration decode(dynamic value) =>
Duration(minutes: int.parse((value as String).replaceAll("m", "")));
@override
String toJson(Duration object) => "${object.inMinutes}m";
String encode(Duration self) => "${self.inMinutes}m";
}

View File

@@ -1,35 +1,37 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:dart_mappable/dart_mappable.dart';
part 'singbox_rule.freezed.dart';
part 'singbox_rule.g.dart';
part 'singbox_rule.mapper.dart';
@freezed
class SingboxRule with _$SingboxRule {
const SingboxRule._();
@MappableClass()
class SingboxRule with SingboxRuleMappable {
const SingboxRule({
this.domains,
this.ip,
this.port,
this.protocol,
this.network = RuleNetwork.tcpAndUdp,
this.outbound = RuleOutbound.proxy,
});
@JsonSerializable(fieldRename: FieldRename.kebab)
const factory SingboxRule({
String? domains,
String? ip,
String? port,
String? protocol,
@Default(RuleNetwork.tcpAndUdp) RuleNetwork network,
@Default(RuleOutbound.proxy) RuleOutbound outbound,
}) = _SingboxRule;
factory SingboxRule.fromJson(Map<String, dynamic> json) =>
_$SingboxRuleFromJson(json);
final String? domains;
final String? ip;
final String? port;
final String? protocol;
final RuleNetwork network;
final RuleOutbound outbound;
}
@MappableEnum()
enum RuleOutbound { proxy, bypass, block }
@JsonEnum(valueField: 'key')
@MappableEnum()
enum RuleNetwork {
tcpAndUdp(""),
tcp("tcp"),
udp("udp");
@MappableValue("")
tcpAndUdp,
const RuleNetwork(this.key);
@MappableValue("tcp")
tcp,
final String? key;
@MappableValue("udp")
udp;
}

View File

@@ -121,7 +121,7 @@ class FFISingboxService with InfraLogger implements SingboxService {
return TaskEither(
() => CombineWorker().execute(
() {
final json = jsonEncode(options.toJson());
final json = options.toJson();
final err = _box
.changeConfigOptions(json.toNativeUtf8().cast())
.cast<Utf8>()

View File

@@ -80,7 +80,7 @@ class PlatformSingboxService with InfraLogger implements SingboxService {
loggy.debug("changing options");
await methodChannel.invokeMethod(
"change_config_options",
jsonEncode(options.toJson()),
options.toJson(),
);
return right(unit);
},