Add proxy routing and sing-box support
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2024-2026 Fabian Freund.
|
||||
*
|
||||
* This file is part of WebLibre
|
||||
* (see https://weblibre.eu).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import 'package:fast_equatable/fast_equatable.dart';
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
part 'proxy_dns_override.g.dart';
|
||||
|
||||
/// Mirrors sing-box's `dns.strategy` field.
|
||||
enum ProxyDnsDomainStrategy { auto, preferIpv4, preferIpv6, ipv4Only, ipv6Only }
|
||||
|
||||
extension ProxyDnsDomainStrategyExt on ProxyDnsDomainStrategy {
|
||||
String get singboxValue => switch (this) {
|
||||
ProxyDnsDomainStrategy.auto => '',
|
||||
ProxyDnsDomainStrategy.preferIpv4 => 'prefer_ipv4',
|
||||
ProxyDnsDomainStrategy.preferIpv6 => 'prefer_ipv6',
|
||||
ProxyDnsDomainStrategy.ipv4Only => 'ipv4_only',
|
||||
ProxyDnsDomainStrategy.ipv6Only => 'ipv6_only',
|
||||
};
|
||||
}
|
||||
|
||||
@JsonSerializable(includeIfNull: true)
|
||||
class ProxyDnsOverride with FastEquatable {
|
||||
/// Single DNS server resolved through this profile's own outbound.
|
||||
final String? remoteServerAddress;
|
||||
|
||||
final ProxyDnsDomainStrategy domainStrategy;
|
||||
|
||||
ProxyDnsOverride({
|
||||
this.remoteServerAddress,
|
||||
this.domainStrategy = ProxyDnsDomainStrategy.preferIpv4,
|
||||
});
|
||||
|
||||
factory ProxyDnsOverride.fromJson(Map<String, dynamic> json) =>
|
||||
_$ProxyDnsOverrideFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$ProxyDnsOverrideToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get hashParameters => [remoteServerAddress, domainStrategy];
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'proxy_dns_override.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
ProxyDnsOverride _$ProxyDnsOverrideFromJson(Map<String, dynamic> json) =>
|
||||
ProxyDnsOverride(
|
||||
remoteServerAddress: json['remoteServerAddress'] as String?,
|
||||
domainStrategy:
|
||||
$enumDecodeNullable(
|
||||
_$ProxyDnsDomainStrategyEnumMap,
|
||||
json['domainStrategy'],
|
||||
) ??
|
||||
ProxyDnsDomainStrategy.preferIpv4,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$ProxyDnsOverrideToJson(
|
||||
ProxyDnsOverride instance,
|
||||
) => <String, dynamic>{
|
||||
'remoteServerAddress': instance.remoteServerAddress,
|
||||
'domainStrategy': _$ProxyDnsDomainStrategyEnumMap[instance.domainStrategy]!,
|
||||
};
|
||||
|
||||
const _$ProxyDnsDomainStrategyEnumMap = {
|
||||
ProxyDnsDomainStrategy.auto: 'auto',
|
||||
ProxyDnsDomainStrategy.preferIpv4: 'preferIpv4',
|
||||
ProxyDnsDomainStrategy.preferIpv6: 'preferIpv6',
|
||||
ProxyDnsDomainStrategy.ipv4Only: 'ipv4Only',
|
||||
ProxyDnsDomainStrategy.ipv6Only: 'ipv6Only',
|
||||
};
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2024-2026 Fabian Freund.
|
||||
*
|
||||
* This file is part of WebLibre
|
||||
* (see https://weblibre.eu).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import 'package:copy_with_extension/copy_with_extension.dart';
|
||||
import 'package:fast_equatable/fast_equatable.dart';
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:weblibre/features/proxy/data/proxy_connection.dart';
|
||||
|
||||
part 'proxy_routing_settings.g.dart';
|
||||
|
||||
enum ProxyRegularTabRoutingMode { container, all }
|
||||
|
||||
@CopyWith()
|
||||
@JsonSerializable(includeIfNull: true, constructor: 'withDefaults')
|
||||
class ProxyRoutingSettings with FastEquatable {
|
||||
final ProxyRegularTabRoutingMode regularTabsMode;
|
||||
|
||||
@JsonKey(
|
||||
fromJson: _proxyConnectionIdFromJson,
|
||||
toJson: _proxyConnectionIdToJson,
|
||||
)
|
||||
final ProxyConnectionId? regularTabsProxyConnectionId;
|
||||
|
||||
@JsonKey(
|
||||
fromJson: _proxyConnectionIdFromJson,
|
||||
toJson: _proxyConnectionIdToJson,
|
||||
)
|
||||
final ProxyConnectionId? privateTabsProxyConnectionId;
|
||||
|
||||
ProxyRoutingSettings({
|
||||
required this.regularTabsMode,
|
||||
required this.regularTabsProxyConnectionId,
|
||||
required this.privateTabsProxyConnectionId,
|
||||
});
|
||||
|
||||
ProxyRoutingSettings.withDefaults({
|
||||
ProxyRegularTabRoutingMode? regularTabsMode,
|
||||
this.regularTabsProxyConnectionId,
|
||||
this.privateTabsProxyConnectionId,
|
||||
}) : regularTabsMode =
|
||||
regularTabsMode ?? ProxyRegularTabRoutingMode.container;
|
||||
|
||||
factory ProxyRoutingSettings.fromJson(Map<String, dynamic> json) =>
|
||||
_$ProxyRoutingSettingsFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$ProxyRoutingSettingsToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get hashParameters => [
|
||||
regularTabsMode,
|
||||
regularTabsProxyConnectionId,
|
||||
privateTabsProxyConnectionId,
|
||||
];
|
||||
}
|
||||
|
||||
ProxyConnectionId? _proxyConnectionIdFromJson(String? json) =>
|
||||
ProxyConnectionId.decode(json);
|
||||
|
||||
String? _proxyConnectionIdToJson(ProxyConnectionId? object) => object?.encode();
|
||||
@@ -0,0 +1,136 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'proxy_routing_settings.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// CopyWithGenerator
|
||||
// **************************************************************************
|
||||
|
||||
abstract class _$ProxyRoutingSettingsCWProxy {
|
||||
ProxyRoutingSettings regularTabsMode(
|
||||
ProxyRegularTabRoutingMode regularTabsMode,
|
||||
);
|
||||
|
||||
ProxyRoutingSettings regularTabsProxyConnectionId(
|
||||
ProxyConnectionId? regularTabsProxyConnectionId,
|
||||
);
|
||||
|
||||
ProxyRoutingSettings privateTabsProxyConnectionId(
|
||||
ProxyConnectionId? privateTabsProxyConnectionId,
|
||||
);
|
||||
|
||||
/// Creates a new instance with the provided field values.
|
||||
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `ProxyRoutingSettings(...).copyWith.fieldName(value)`.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// ProxyRoutingSettings(...).copyWith(id: 12, name: "My name")
|
||||
/// ```
|
||||
ProxyRoutingSettings call({
|
||||
ProxyRegularTabRoutingMode regularTabsMode,
|
||||
ProxyConnectionId? regularTabsProxyConnectionId,
|
||||
ProxyConnectionId? privateTabsProxyConnectionId,
|
||||
});
|
||||
}
|
||||
|
||||
/// Callable proxy for `copyWith` functionality.
|
||||
/// Use as `instanceOfProxyRoutingSettings.copyWith(...)` or call `instanceOfProxyRoutingSettings.copyWith.fieldName(value)` for a single field.
|
||||
class _$ProxyRoutingSettingsCWProxyImpl
|
||||
implements _$ProxyRoutingSettingsCWProxy {
|
||||
const _$ProxyRoutingSettingsCWProxyImpl(this._value);
|
||||
|
||||
final ProxyRoutingSettings _value;
|
||||
|
||||
@override
|
||||
ProxyRoutingSettings regularTabsMode(
|
||||
ProxyRegularTabRoutingMode regularTabsMode,
|
||||
) => call(regularTabsMode: regularTabsMode);
|
||||
|
||||
@override
|
||||
ProxyRoutingSettings regularTabsProxyConnectionId(
|
||||
ProxyConnectionId? regularTabsProxyConnectionId,
|
||||
) => call(regularTabsProxyConnectionId: regularTabsProxyConnectionId);
|
||||
|
||||
@override
|
||||
ProxyRoutingSettings privateTabsProxyConnectionId(
|
||||
ProxyConnectionId? privateTabsProxyConnectionId,
|
||||
) => call(privateTabsProxyConnectionId: privateTabsProxyConnectionId);
|
||||
|
||||
@override
|
||||
/// Creates a new instance with the provided field values.
|
||||
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `ProxyRoutingSettings(...).copyWith.fieldName(value)`.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// ProxyRoutingSettings(...).copyWith(id: 12, name: "My name")
|
||||
/// ```
|
||||
ProxyRoutingSettings call({
|
||||
Object? regularTabsMode = const $CopyWithPlaceholder(),
|
||||
Object? regularTabsProxyConnectionId = const $CopyWithPlaceholder(),
|
||||
Object? privateTabsProxyConnectionId = const $CopyWithPlaceholder(),
|
||||
}) {
|
||||
return ProxyRoutingSettings(
|
||||
regularTabsMode:
|
||||
regularTabsMode == const $CopyWithPlaceholder() ||
|
||||
regularTabsMode == null
|
||||
? _value.regularTabsMode
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: regularTabsMode as ProxyRegularTabRoutingMode,
|
||||
regularTabsProxyConnectionId:
|
||||
regularTabsProxyConnectionId == const $CopyWithPlaceholder()
|
||||
? _value.regularTabsProxyConnectionId
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: regularTabsProxyConnectionId as ProxyConnectionId?,
|
||||
privateTabsProxyConnectionId:
|
||||
privateTabsProxyConnectionId == const $CopyWithPlaceholder()
|
||||
? _value.privateTabsProxyConnectionId
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: privateTabsProxyConnectionId as ProxyConnectionId?,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension $ProxyRoutingSettingsCopyWith on ProxyRoutingSettings {
|
||||
/// Returns a callable class used to build a new instance with modified fields.
|
||||
/// Example: `instanceOfProxyRoutingSettings.copyWith(...)` or `instanceOfProxyRoutingSettings.copyWith.fieldName(...)`.
|
||||
// ignore: library_private_types_in_public_api
|
||||
_$ProxyRoutingSettingsCWProxy get copyWith =>
|
||||
_$ProxyRoutingSettingsCWProxyImpl(this);
|
||||
}
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
ProxyRoutingSettings _$ProxyRoutingSettingsFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) => ProxyRoutingSettings.withDefaults(
|
||||
regularTabsMode: $enumDecodeNullable(
|
||||
_$ProxyRegularTabRoutingModeEnumMap,
|
||||
json['regularTabsMode'],
|
||||
),
|
||||
regularTabsProxyConnectionId: _proxyConnectionIdFromJson(
|
||||
json['regularTabsProxyConnectionId'] as String?,
|
||||
),
|
||||
privateTabsProxyConnectionId: _proxyConnectionIdFromJson(
|
||||
json['privateTabsProxyConnectionId'] as String?,
|
||||
),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$ProxyRoutingSettingsToJson(
|
||||
ProxyRoutingSettings instance,
|
||||
) => <String, dynamic>{
|
||||
'regularTabsMode':
|
||||
_$ProxyRegularTabRoutingModeEnumMap[instance.regularTabsMode]!,
|
||||
'regularTabsProxyConnectionId': _proxyConnectionIdToJson(
|
||||
instance.regularTabsProxyConnectionId,
|
||||
),
|
||||
'privateTabsProxyConnectionId': _proxyConnectionIdToJson(
|
||||
instance.privateTabsProxyConnectionId,
|
||||
),
|
||||
};
|
||||
|
||||
const _$ProxyRegularTabRoutingModeEnumMap = {
|
||||
ProxyRegularTabRoutingMode.container: 'container',
|
||||
ProxyRegularTabRoutingMode.all: 'all',
|
||||
};
|
||||
@@ -25,13 +25,9 @@ part 'tor_settings.g.dart';
|
||||
|
||||
enum TorConnectionConfig { auto, direct, obfs4, snowflake }
|
||||
|
||||
enum TorRegularTabProxyMode { container, all }
|
||||
|
||||
@CopyWith()
|
||||
@JsonSerializable(includeIfNull: true, constructor: 'withDefaults')
|
||||
class TorSettings with FastEquatable {
|
||||
final TorRegularTabProxyMode proxyRegularTabsMode;
|
||||
final bool proxyPrivateTabsTor;
|
||||
final TorConnectionConfig config;
|
||||
final bool requireBridge;
|
||||
final bool fetchRemoteBridges;
|
||||
@@ -39,8 +35,6 @@ class TorSettings with FastEquatable {
|
||||
final String? exitNodeCountry;
|
||||
|
||||
TorSettings({
|
||||
required this.proxyRegularTabsMode,
|
||||
required this.proxyPrivateTabsTor,
|
||||
required this.config,
|
||||
required this.requireBridge,
|
||||
required this.fetchRemoteBridges,
|
||||
@@ -49,17 +43,12 @@ class TorSettings with FastEquatable {
|
||||
});
|
||||
|
||||
TorSettings.withDefaults({
|
||||
TorRegularTabProxyMode? proxyRegularTabsMode,
|
||||
bool? proxyPrivateTabsTor,
|
||||
TorConnectionConfig? config,
|
||||
bool? requireBridge,
|
||||
bool? fetchRemoteBridges,
|
||||
this.entryNodeCountry,
|
||||
this.exitNodeCountry,
|
||||
}) : proxyRegularTabsMode =
|
||||
proxyRegularTabsMode ?? TorRegularTabProxyMode.container,
|
||||
proxyPrivateTabsTor = proxyPrivateTabsTor ?? false,
|
||||
config = config ?? TorConnectionConfig.auto,
|
||||
}) : config = config ?? TorConnectionConfig.auto,
|
||||
requireBridge = requireBridge ?? false,
|
||||
fetchRemoteBridges = fetchRemoteBridges ?? true;
|
||||
|
||||
@@ -70,8 +59,6 @@ class TorSettings with FastEquatable {
|
||||
|
||||
@override
|
||||
List<Object?> get hashParameters => [
|
||||
proxyRegularTabsMode,
|
||||
proxyPrivateTabsTor,
|
||||
config,
|
||||
requireBridge,
|
||||
fetchRemoteBridges,
|
||||
|
||||
@@ -7,10 +7,6 @@ part of 'tor_settings.dart';
|
||||
// **************************************************************************
|
||||
|
||||
abstract class _$TorSettingsCWProxy {
|
||||
TorSettings proxyRegularTabsMode(TorRegularTabProxyMode proxyRegularTabsMode);
|
||||
|
||||
TorSettings proxyPrivateTabsTor(bool proxyPrivateTabsTor);
|
||||
|
||||
TorSettings config(TorConnectionConfig config);
|
||||
|
||||
TorSettings requireBridge(bool requireBridge);
|
||||
@@ -29,8 +25,6 @@ abstract class _$TorSettingsCWProxy {
|
||||
/// TorSettings(...).copyWith(id: 12, name: "My name")
|
||||
/// ```
|
||||
TorSettings call({
|
||||
TorRegularTabProxyMode proxyRegularTabsMode,
|
||||
bool proxyPrivateTabsTor,
|
||||
TorConnectionConfig config,
|
||||
bool requireBridge,
|
||||
bool fetchRemoteBridges,
|
||||
@@ -46,15 +40,6 @@ class _$TorSettingsCWProxyImpl implements _$TorSettingsCWProxy {
|
||||
|
||||
final TorSettings _value;
|
||||
|
||||
@override
|
||||
TorSettings proxyRegularTabsMode(
|
||||
TorRegularTabProxyMode proxyRegularTabsMode,
|
||||
) => call(proxyRegularTabsMode: proxyRegularTabsMode);
|
||||
|
||||
@override
|
||||
TorSettings proxyPrivateTabsTor(bool proxyPrivateTabsTor) =>
|
||||
call(proxyPrivateTabsTor: proxyPrivateTabsTor);
|
||||
|
||||
@override
|
||||
TorSettings config(TorConnectionConfig config) => call(config: config);
|
||||
|
||||
@@ -83,8 +68,6 @@ class _$TorSettingsCWProxyImpl implements _$TorSettingsCWProxy {
|
||||
/// TorSettings(...).copyWith(id: 12, name: "My name")
|
||||
/// ```
|
||||
TorSettings call({
|
||||
Object? proxyRegularTabsMode = const $CopyWithPlaceholder(),
|
||||
Object? proxyPrivateTabsTor = const $CopyWithPlaceholder(),
|
||||
Object? config = const $CopyWithPlaceholder(),
|
||||
Object? requireBridge = const $CopyWithPlaceholder(),
|
||||
Object? fetchRemoteBridges = const $CopyWithPlaceholder(),
|
||||
@@ -92,18 +75,6 @@ class _$TorSettingsCWProxyImpl implements _$TorSettingsCWProxy {
|
||||
Object? exitNodeCountry = const $CopyWithPlaceholder(),
|
||||
}) {
|
||||
return TorSettings(
|
||||
proxyRegularTabsMode:
|
||||
proxyRegularTabsMode == const $CopyWithPlaceholder() ||
|
||||
proxyRegularTabsMode == null
|
||||
? _value.proxyRegularTabsMode
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: proxyRegularTabsMode as TorRegularTabProxyMode,
|
||||
proxyPrivateTabsTor:
|
||||
proxyPrivateTabsTor == const $CopyWithPlaceholder() ||
|
||||
proxyPrivateTabsTor == null
|
||||
? _value.proxyPrivateTabsTor
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: proxyPrivateTabsTor as bool,
|
||||
config: config == const $CopyWithPlaceholder() || config == null
|
||||
? _value.config
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
@@ -144,11 +115,6 @@ extension $TorSettingsCopyWith on TorSettings {
|
||||
|
||||
TorSettings _$TorSettingsFromJson(Map<String, dynamic> json) =>
|
||||
TorSettings.withDefaults(
|
||||
proxyRegularTabsMode: $enumDecodeNullable(
|
||||
_$TorRegularTabProxyModeEnumMap,
|
||||
json['proxyRegularTabsMode'],
|
||||
),
|
||||
proxyPrivateTabsTor: json['proxyPrivateTabsTor'] as bool?,
|
||||
config: $enumDecodeNullable(_$TorConnectionConfigEnumMap, json['config']),
|
||||
requireBridge: json['requireBridge'] as bool?,
|
||||
fetchRemoteBridges: json['fetchRemoteBridges'] as bool?,
|
||||
@@ -158,9 +124,6 @@ TorSettings _$TorSettingsFromJson(Map<String, dynamic> json) =>
|
||||
|
||||
Map<String, dynamic> _$TorSettingsToJson(TorSettings instance) =>
|
||||
<String, dynamic>{
|
||||
'proxyRegularTabsMode':
|
||||
_$TorRegularTabProxyModeEnumMap[instance.proxyRegularTabsMode]!,
|
||||
'proxyPrivateTabsTor': instance.proxyPrivateTabsTor,
|
||||
'config': _$TorConnectionConfigEnumMap[instance.config]!,
|
||||
'requireBridge': instance.requireBridge,
|
||||
'fetchRemoteBridges': instance.fetchRemoteBridges,
|
||||
@@ -168,11 +131,6 @@ Map<String, dynamic> _$TorSettingsToJson(TorSettings instance) =>
|
||||
'exitNodeCountry': instance.exitNodeCountry,
|
||||
};
|
||||
|
||||
const _$TorRegularTabProxyModeEnumMap = {
|
||||
TorRegularTabProxyMode.container: 'container',
|
||||
TorRegularTabProxyMode.all: 'all',
|
||||
};
|
||||
|
||||
const _$TorConnectionConfigEnumMap = {
|
||||
TorConnectionConfig.auto: 'auto',
|
||||
TorConnectionConfig.direct: 'direct',
|
||||
|
||||
Reference in New Issue
Block a user