initial
This commit is contained in:
@@ -21,6 +21,7 @@ import 'dart:async';
|
|||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:flutter_background_service/flutter_background_service.dart';
|
import 'package:flutter_background_service/flutter_background_service.dart';
|
||||||
|
import 'package:pluggable_transports_proxy/pluggable_transports_proxy.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:rxdart/rxdart.dart';
|
import 'package:rxdart/rxdart.dart';
|
||||||
import 'package:weblibre/core/logger.dart';
|
import 'package:weblibre/core/logger.dart';
|
||||||
@@ -36,8 +37,12 @@ class _TorService {
|
|||||||
|
|
||||||
ValueStream<int?> get portStream => _portSubject.stream;
|
ValueStream<int?> get portStream => _portSubject.stream;
|
||||||
|
|
||||||
Future<void> start() async {
|
Future<void> start({ProxyType? proxyType, String? bridgeLines}) async {
|
||||||
await service.startService();
|
await service.startService();
|
||||||
|
service.invoke('start', {
|
||||||
|
if (proxyType != null) 'proxyType': proxyType.name,
|
||||||
|
if (bridgeLines != null) 'bridgeLines': bridgeLines,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> requestSync() async {
|
Future<void> requestSync() async {
|
||||||
|
|||||||
@@ -19,12 +19,15 @@
|
|||||||
*/
|
*/
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter_background_service/flutter_background_service.dart';
|
import 'package:flutter_background_service/flutter_background_service.dart';
|
||||||
|
import 'package:pluggable_transports_proxy/pluggable_transports_proxy.dart';
|
||||||
import 'package:tor/tor.dart';
|
import 'package:tor/tor.dart';
|
||||||
|
|
||||||
@pragma('vm:entry-point')
|
@pragma('vm:entry-point')
|
||||||
Future<void> onStart(ServiceInstance service) async {
|
Future<void> onStart(ServiceInstance service) async {
|
||||||
Timer? timeout;
|
Timer? timeout;
|
||||||
|
final startedProxyType = <ProxyType>{};
|
||||||
|
|
||||||
await Tor.init();
|
await Tor.init();
|
||||||
|
|
||||||
@@ -37,6 +40,12 @@ Future<void> onStart(ServiceInstance service) async {
|
|||||||
timeout = null;
|
timeout = null;
|
||||||
|
|
||||||
Tor.instance.stop();
|
Tor.instance.stop();
|
||||||
|
|
||||||
|
for (final proxyType in startedProxyType) {
|
||||||
|
await IPtProxyController().stop(proxyType);
|
||||||
|
}
|
||||||
|
startedProxyType.clear();
|
||||||
|
|
||||||
service.invoke('portUpdate', {'port': -1});
|
service.invoke('portUpdate', {'port': -1});
|
||||||
|
|
||||||
await portSub.cancel();
|
await portSub.cancel();
|
||||||
@@ -52,7 +61,36 @@ Future<void> onStart(ServiceInstance service) async {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
await Tor.instance.start();
|
Future<void> startService(ProxyType? proxyType, String? bridgeLines) async {
|
||||||
|
if (proxyType != null) {
|
||||||
|
final port = await IPtProxyController().start(proxyType, "");
|
||||||
|
startedProxyType.add(proxyType);
|
||||||
|
|
||||||
|
switch (proxyType) {
|
||||||
|
case ProxyType.obfs4:
|
||||||
|
await Tor.instance.start(obfs4Port: port, bridgeLines: bridgeLines);
|
||||||
|
case ProxyType.meekLite:
|
||||||
|
throw UnimplementedError();
|
||||||
|
case ProxyType.webtunnel:
|
||||||
|
throw UnimplementedError();
|
||||||
|
case ProxyType.snowflake:
|
||||||
|
await Tor.instance.start(
|
||||||
|
snowflakePort: port,
|
||||||
|
bridgeLines: bridgeLines,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await Tor.instance.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
service.on("start").listen((event) async {
|
||||||
|
final proxyType = ProxyType.values.firstWhereOrNull(
|
||||||
|
(x) => x.name == event?['proxyType'],
|
||||||
|
);
|
||||||
|
|
||||||
|
await startService(proxyType, event?['bridgeLines'] as String?);
|
||||||
|
});
|
||||||
|
|
||||||
service.on("heartbeat").listen((event) {
|
service.on("heartbeat").listen((event) {
|
||||||
// logger.d('Received tor heartbeat');
|
// logger.d('Received tor heartbeat');
|
||||||
|
|||||||
+3
-3
@@ -51,6 +51,8 @@ dependencies:
|
|||||||
path: ^1.9.1
|
path: ^1.9.1
|
||||||
path_provider: ^2.1.5
|
path_provider: ^2.1.5
|
||||||
permission_handler: ^12.0.1
|
permission_handler: ^12.0.1
|
||||||
|
pluggable_transports_proxy:
|
||||||
|
path: ../packages/pluggable_transports_proxy
|
||||||
pretty_qr_code: ^3.5.0
|
pretty_qr_code: ^3.5.0
|
||||||
riverpod: ^2.6.1
|
riverpod: ^2.6.1
|
||||||
riverpod_annotation: ^2.6.1
|
riverpod_annotation: ^2.6.1
|
||||||
@@ -75,9 +77,7 @@ dependencies:
|
|||||||
text_scroll: ^0.2.0
|
text_scroll: ^0.2.0
|
||||||
timeago: ^3.7.1
|
timeago: ^3.7.1
|
||||||
tor:
|
tor:
|
||||||
git:
|
path: /home/fafre/development/repos/tor
|
||||||
url: https://github.com/FaFre/tor.git
|
|
||||||
ref: update
|
|
||||||
universal_io: ^2.2.2
|
universal_io: ^2.2.2
|
||||||
uri_to_file:
|
uri_to_file:
|
||||||
git:
|
git:
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
# Miscellaneous
|
||||||
|
*.class
|
||||||
|
*.log
|
||||||
|
*.pyc
|
||||||
|
*.swp
|
||||||
|
.DS_Store
|
||||||
|
.atom/
|
||||||
|
.build/
|
||||||
|
.buildlog/
|
||||||
|
.history
|
||||||
|
.svn/
|
||||||
|
.swiftpm/
|
||||||
|
migrate_working_dir/
|
||||||
|
|
||||||
|
# IntelliJ related
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# The .vscode folder contains launch configuration and tasks you configure in
|
||||||
|
# VS Code which you may wish to be included in version control, so this line
|
||||||
|
# is commented out by default.
|
||||||
|
#.vscode/
|
||||||
|
|
||||||
|
# Flutter/Dart/Pub related
|
||||||
|
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
|
||||||
|
/pubspec.lock
|
||||||
|
**/doc/api/
|
||||||
|
.dart_tool/
|
||||||
|
.flutter-plugins-dependencies
|
||||||
|
/build/
|
||||||
|
/coverage/
|
||||||
|
.gradle/
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# This file tracks properties of this Flutter project.
|
||||||
|
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||||
|
#
|
||||||
|
# This file should be version controlled and should not be manually edited.
|
||||||
|
|
||||||
|
version:
|
||||||
|
revision: "20f82749394e68bcfbbeee96bad384abaae09c13"
|
||||||
|
channel: "stable"
|
||||||
|
|
||||||
|
project_type: plugin
|
||||||
|
|
||||||
|
# Tracks metadata for the flutter migrate command
|
||||||
|
migration:
|
||||||
|
platforms:
|
||||||
|
- platform: root
|
||||||
|
create_revision: 20f82749394e68bcfbbeee96bad384abaae09c13
|
||||||
|
base_revision: 20f82749394e68bcfbbeee96bad384abaae09c13
|
||||||
|
- platform: android
|
||||||
|
create_revision: 20f82749394e68bcfbbeee96bad384abaae09c13
|
||||||
|
base_revision: 20f82749394e68bcfbbeee96bad384abaae09c13
|
||||||
|
|
||||||
|
# User provided section
|
||||||
|
|
||||||
|
# List of Local paths (relative to this file) that should be
|
||||||
|
# ignored by the migrate tool.
|
||||||
|
#
|
||||||
|
# Files that are not part of the templates will be ignored by default.
|
||||||
|
unmanaged_files:
|
||||||
|
- 'lib/main.dart'
|
||||||
|
- 'ios/Runner.xcodeproj/project.pbxproj'
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
## 0.0.1
|
||||||
|
|
||||||
|
* TODO: Describe initial release.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
TODO: Add your license here.
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# pluggable_transports_proxy
|
||||||
|
|
||||||
|
A new Flutter plugin project.
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
This project is a starting point for a Flutter
|
||||||
|
[plug-in package](https://flutter.dev/to/develop-plugins),
|
||||||
|
a specialized package that includes platform-specific implementation code for
|
||||||
|
Android and/or iOS.
|
||||||
|
|
||||||
|
For help getting started with Flutter development, view the
|
||||||
|
[online documentation](https://docs.flutter.dev), which offers tutorials,
|
||||||
|
samples, guidance on mobile development, and a full API reference.
|
||||||
|
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
# This file configures the static analysis results for your project (errors,
|
||||||
|
# warnings, and lints).
|
||||||
|
#
|
||||||
|
# This enables the 'recommended' set of lints from `package:lints`.
|
||||||
|
# This set helps identify many issues that may lead to problems when running
|
||||||
|
# or consuming Dart code, and enforces writing Dart using a single, idiomatic
|
||||||
|
# style and format.
|
||||||
|
#
|
||||||
|
# If you want a smaller set of lints you can change this to specify
|
||||||
|
# 'package:lints/core.yaml'. These are just the most critical lints
|
||||||
|
# (the recommended set includes the core lints).
|
||||||
|
# The core lints are also what is used by pub.dev for scoring packages.
|
||||||
|
|
||||||
|
include: package:lint/package.yaml
|
||||||
|
# Uncomment the following section to specify additional rules.
|
||||||
|
|
||||||
|
linter:
|
||||||
|
rules:
|
||||||
|
unawaited_futures: true
|
||||||
|
discarded_futures: true
|
||||||
|
collection_methods_unrelated_type: true
|
||||||
|
|
||||||
|
analyzer:
|
||||||
|
plugins:
|
||||||
|
- custom_lint
|
||||||
|
exclude:
|
||||||
|
- "**.g.dart"
|
||||||
|
- "**.swagger.dart"
|
||||||
|
- "**.freezed.dart"
|
||||||
|
- "**.chopper.dart"
|
||||||
|
# For more information about the core and recommended set of lints, see
|
||||||
|
# https://dart.dev/go/core-lints
|
||||||
|
|
||||||
|
# For additional information about configuring this file, see
|
||||||
|
# https://dart.dev/guides/language/analysis-options
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
*.iml
|
||||||
|
.gradle
|
||||||
|
/local.properties
|
||||||
|
/.idea/workspace.xml
|
||||||
|
/.idea/libraries
|
||||||
|
.DS_Store
|
||||||
|
/build
|
||||||
|
/captures
|
||||||
|
.cxx
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
group = "eu.weblibre.pluggable_transports_proxy"
|
||||||
|
version = "1.0-SNAPSHOT"
|
||||||
|
|
||||||
|
buildscript {
|
||||||
|
ext.kotlin_version = "2.1.0"
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
classpath("com.android.tools.build:gradle:8.9.1")
|
||||||
|
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: "com.android.library"
|
||||||
|
apply plugin: "kotlin-android"
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "eu.weblibre.pluggable_transports_proxy"
|
||||||
|
|
||||||
|
compileSdk = 36
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_11
|
||||||
|
targetCompatibility = JavaVersion.VERSION_11
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = JavaVersion.VERSION_11
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main.java.srcDirs += "src/main/kotlin"
|
||||||
|
test.java.srcDirs += "src/test/kotlin"
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdk = 24
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
testImplementation("org.jetbrains.kotlin:kotlin-test")
|
||||||
|
testImplementation("org.mockito:mockito-core:5.0.0")
|
||||||
|
}
|
||||||
|
|
||||||
|
testOptions {
|
||||||
|
unitTests.all {
|
||||||
|
useJUnitPlatform()
|
||||||
|
|
||||||
|
testLogging {
|
||||||
|
events "passed", "skipped", "failed", "standardOut", "standardError"
|
||||||
|
outputs.upToDateWhen {false}
|
||||||
|
showStandardStreams = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'com.netzarchitekten:IPtProxy:4.2.2'
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
rootProject.name = 'pluggable_transports_proxy'
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="eu.weblibre.pluggable_transports_proxy">
|
||||||
|
</manifest>
|
||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
package eu.weblibre.pluggable_transports_proxy
|
||||||
|
|
||||||
|
import IPtProxy.Controller
|
||||||
|
import eu.weblibre.pluggable_transports_proxy.pigeons.IPtProxyController
|
||||||
|
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
||||||
|
import io.flutter.plugin.common.MethodChannel
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
/** PluggableTransportsProxyPlugin */
|
||||||
|
class PluggableTransportsProxyPlugin : FlutterPlugin {
|
||||||
|
private lateinit var channel: MethodChannel
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@Volatile
|
||||||
|
private var INSTANCE: Controller? = null
|
||||||
|
|
||||||
|
fun getController(ptDirPath: String): Controller {
|
||||||
|
return INSTANCE ?: synchronized(this) {
|
||||||
|
INSTANCE ?: Controller(ptDirPath, true, false, "INFO", null).also { INSTANCE = it }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
|
||||||
|
val ptDir = File(flutterPluginBinding.applicationContext.cacheDir, "pt_state")
|
||||||
|
val ptc = getController(ptDir.path)
|
||||||
|
|
||||||
|
IPtProxyController.setUp(flutterPluginBinding.binaryMessenger, ProxyImpl(controller = ptc))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
|
||||||
|
// Controller instance remains alive for reuse
|
||||||
|
}
|
||||||
|
}
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
package eu.weblibre.pluggable_transports_proxy
|
||||||
|
|
||||||
|
import eu.weblibre.pluggable_transports_proxy.pigeons.IPtProxyController
|
||||||
|
import eu.weblibre.pluggable_transports_proxy.pigeons.ProxyType
|
||||||
|
|
||||||
|
class ProxyImpl(val controller: IPtProxy.Controller) : IPtProxyController {
|
||||||
|
override fun start(
|
||||||
|
proxyType: ProxyType,
|
||||||
|
proxy: String
|
||||||
|
): Long {
|
||||||
|
val type = when (proxyType) {
|
||||||
|
ProxyType.OBFS4 -> IPtProxy.IPtProxy.Obfs4
|
||||||
|
ProxyType.MEEK_LITE -> IPtProxy.IPtProxy.MeekLite
|
||||||
|
ProxyType.WEBTUNNEL -> IPtProxy.IPtProxy.Webtunnel
|
||||||
|
ProxyType.SNOWFLAKE -> IPtProxy.IPtProxy.Snowflake
|
||||||
|
};
|
||||||
|
|
||||||
|
controller.start(type, proxy)
|
||||||
|
|
||||||
|
return controller.port(type)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun stop(proxyType: ProxyType) {
|
||||||
|
val type = when (proxyType) {
|
||||||
|
ProxyType.OBFS4 -> IPtProxy.IPtProxy.Obfs4
|
||||||
|
ProxyType.MEEK_LITE -> IPtProxy.IPtProxy.MeekLite
|
||||||
|
ProxyType.WEBTUNNEL -> IPtProxy.IPtProxy.Webtunnel
|
||||||
|
ProxyType.SNOWFLAKE -> IPtProxy.IPtProxy.Snowflake
|
||||||
|
};
|
||||||
|
|
||||||
|
controller.stop(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
+137
@@ -0,0 +1,137 @@
|
|||||||
|
// Autogenerated from Pigeon (v26.0.1), do not edit directly.
|
||||||
|
// See also: https://pub.dev/packages/pigeon
|
||||||
|
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
|
||||||
|
|
||||||
|
package eu.weblibre.pluggable_transports_proxy.pigeons
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import io.flutter.plugin.common.BasicMessageChannel
|
||||||
|
import io.flutter.plugin.common.BinaryMessenger
|
||||||
|
import io.flutter.plugin.common.EventChannel
|
||||||
|
import io.flutter.plugin.common.MessageCodec
|
||||||
|
import io.flutter.plugin.common.StandardMethodCodec
|
||||||
|
import io.flutter.plugin.common.StandardMessageCodec
|
||||||
|
import java.io.ByteArrayOutputStream
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
private object ProxyPigeonUtils {
|
||||||
|
|
||||||
|
fun wrapResult(result: Any?): List<Any?> {
|
||||||
|
return listOf(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun wrapError(exception: Throwable): List<Any?> {
|
||||||
|
return if (exception is FlutterError) {
|
||||||
|
listOf(
|
||||||
|
exception.code,
|
||||||
|
exception.message,
|
||||||
|
exception.details
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
listOf(
|
||||||
|
exception.javaClass.simpleName,
|
||||||
|
exception.toString(),
|
||||||
|
"Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error class for passing custom error details to Flutter via a thrown PlatformException.
|
||||||
|
* @property code The error code.
|
||||||
|
* @property message The error message.
|
||||||
|
* @property details The error details. Must be a datatype supported by the api codec.
|
||||||
|
*/
|
||||||
|
class FlutterError (
|
||||||
|
val code: String,
|
||||||
|
override val message: String? = null,
|
||||||
|
val details: Any? = null
|
||||||
|
) : Throwable()
|
||||||
|
|
||||||
|
enum class ProxyType(val raw: Int) {
|
||||||
|
OBFS4(0),
|
||||||
|
MEEK_LITE(1),
|
||||||
|
WEBTUNNEL(2),
|
||||||
|
SNOWFLAKE(3);
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun ofRaw(raw: Int): ProxyType? {
|
||||||
|
return values().firstOrNull { it.raw == raw }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private open class ProxyPigeonCodec : StandardMessageCodec() {
|
||||||
|
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
|
||||||
|
return when (type) {
|
||||||
|
129.toByte() -> {
|
||||||
|
return (readValue(buffer) as Long?)?.let {
|
||||||
|
ProxyType.ofRaw(it.toInt())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> super.readValueOfType(type, buffer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
|
||||||
|
when (value) {
|
||||||
|
is ProxyType -> {
|
||||||
|
stream.write(129)
|
||||||
|
writeValue(stream, value.raw)
|
||||||
|
}
|
||||||
|
else -> super.writeValue(stream, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
||||||
|
interface IPtProxyController {
|
||||||
|
fun start(proxyType: ProxyType, proxy: String): Long
|
||||||
|
fun stop(proxyType: ProxyType)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/** The codec used by IPtProxyController. */
|
||||||
|
val codec: MessageCodec<Any?> by lazy {
|
||||||
|
ProxyPigeonCodec()
|
||||||
|
}
|
||||||
|
/** Sets up an instance of `IPtProxyController` to handle messages through the `binaryMessenger`. */
|
||||||
|
@JvmOverloads
|
||||||
|
fun setUp(binaryMessenger: BinaryMessenger, api: IPtProxyController?, messageChannelSuffix: String = "") {
|
||||||
|
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||||
|
run {
|
||||||
|
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.pluggable_transports_proxy.IPtProxyController.start$separatedMessageChannelSuffix", codec)
|
||||||
|
if (api != null) {
|
||||||
|
channel.setMessageHandler { message, reply ->
|
||||||
|
val args = message as List<Any?>
|
||||||
|
val proxyTypeArg = args[0] as ProxyType
|
||||||
|
val proxyArg = args[1] as String
|
||||||
|
val wrapped: List<Any?> = try {
|
||||||
|
listOf(api.start(proxyTypeArg, proxyArg))
|
||||||
|
} catch (exception: Throwable) {
|
||||||
|
ProxyPigeonUtils.wrapError(exception)
|
||||||
|
}
|
||||||
|
reply.reply(wrapped)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
channel.setMessageHandler(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
run {
|
||||||
|
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.pluggable_transports_proxy.IPtProxyController.stop$separatedMessageChannelSuffix", codec)
|
||||||
|
if (api != null) {
|
||||||
|
channel.setMessageHandler { message, reply ->
|
||||||
|
val args = message as List<Any?>
|
||||||
|
val proxyTypeArg = args[0] as ProxyType
|
||||||
|
val wrapped: List<Any?> = try {
|
||||||
|
api.stop(proxyTypeArg)
|
||||||
|
listOf(null)
|
||||||
|
} catch (exception: Throwable) {
|
||||||
|
ProxyPigeonUtils.wrapError(exception)
|
||||||
|
}
|
||||||
|
reply.reply(wrapped)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
channel.setMessageHandler(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export 'src/pigeons/proxy.g.dart' show IPtProxyController, ProxyType;
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
// Autogenerated from Pigeon (v26.0.1), do not edit directly.
|
||||||
|
// See also: https://pub.dev/packages/pigeon
|
||||||
|
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List;
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer;
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
PlatformException _createConnectionError(String channelName) {
|
||||||
|
return PlatformException(
|
||||||
|
code: 'channel-error',
|
||||||
|
message: 'Unable to establish connection on channel: "$channelName".',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ProxyType {
|
||||||
|
obfs4,
|
||||||
|
meekLite,
|
||||||
|
webtunnel,
|
||||||
|
snowflake,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class _PigeonCodec extends StandardMessageCodec {
|
||||||
|
const _PigeonCodec();
|
||||||
|
@override
|
||||||
|
void writeValue(WriteBuffer buffer, Object? value) {
|
||||||
|
if (value is int) {
|
||||||
|
buffer.putUint8(4);
|
||||||
|
buffer.putInt64(value);
|
||||||
|
} else if (value is ProxyType) {
|
||||||
|
buffer.putUint8(129);
|
||||||
|
writeValue(buffer, value.index);
|
||||||
|
} else {
|
||||||
|
super.writeValue(buffer, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Object? readValueOfType(int type, ReadBuffer buffer) {
|
||||||
|
switch (type) {
|
||||||
|
case 129:
|
||||||
|
final int? value = readValue(buffer) as int?;
|
||||||
|
return value == null ? null : ProxyType.values[value];
|
||||||
|
default:
|
||||||
|
return super.readValueOfType(type, buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class IPtProxyController {
|
||||||
|
/// Constructor for [IPtProxyController]. The [binaryMessenger] named argument is
|
||||||
|
/// available for dependency injection. If it is left null, the default
|
||||||
|
/// BinaryMessenger will be used which routes to the host platform.
|
||||||
|
IPtProxyController({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''})
|
||||||
|
: pigeonVar_binaryMessenger = binaryMessenger,
|
||||||
|
pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
|
||||||
|
final BinaryMessenger? pigeonVar_binaryMessenger;
|
||||||
|
|
||||||
|
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
|
||||||
|
|
||||||
|
final String pigeonVar_messageChannelSuffix;
|
||||||
|
|
||||||
|
Future<int> start(ProxyType proxyType, String proxy) async {
|
||||||
|
final String pigeonVar_channelName = 'dev.flutter.pigeon.pluggable_transports_proxy.IPtProxyController.start$pigeonVar_messageChannelSuffix';
|
||||||
|
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||||
|
pigeonVar_channelName,
|
||||||
|
pigeonChannelCodec,
|
||||||
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
|
);
|
||||||
|
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[proxyType, proxy]);
|
||||||
|
final List<Object?>? pigeonVar_replyList =
|
||||||
|
await pigeonVar_sendFuture as List<Object?>?;
|
||||||
|
if (pigeonVar_replyList == null) {
|
||||||
|
throw _createConnectionError(pigeonVar_channelName);
|
||||||
|
} else if (pigeonVar_replyList.length > 1) {
|
||||||
|
throw PlatformException(
|
||||||
|
code: pigeonVar_replyList[0]! as String,
|
||||||
|
message: pigeonVar_replyList[1] as String?,
|
||||||
|
details: pigeonVar_replyList[2],
|
||||||
|
);
|
||||||
|
} else if (pigeonVar_replyList[0] == null) {
|
||||||
|
throw PlatformException(
|
||||||
|
code: 'null-error',
|
||||||
|
message: 'Host platform returned null value for non-null return value.',
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (pigeonVar_replyList[0] as int?)!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> stop(ProxyType proxyType) async {
|
||||||
|
final String pigeonVar_channelName = 'dev.flutter.pigeon.pluggable_transports_proxy.IPtProxyController.stop$pigeonVar_messageChannelSuffix';
|
||||||
|
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||||
|
pigeonVar_channelName,
|
||||||
|
pigeonChannelCodec,
|
||||||
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
|
);
|
||||||
|
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[proxyType]);
|
||||||
|
final List<Object?>? pigeonVar_replyList =
|
||||||
|
await pigeonVar_sendFuture as List<Object?>?;
|
||||||
|
if (pigeonVar_replyList == null) {
|
||||||
|
throw _createConnectionError(pigeonVar_channelName);
|
||||||
|
} else if (pigeonVar_replyList.length > 1) {
|
||||||
|
throw PlatformException(
|
||||||
|
code: pigeonVar_replyList[0]! as String,
|
||||||
|
message: pigeonVar_replyList[1] as String?,
|
||||||
|
details: pigeonVar_replyList[2],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import 'package:pigeon/pigeon.dart';
|
||||||
|
|
||||||
|
enum ProxyType { obfs4, meekLite, webtunnel, snowflake }
|
||||||
|
|
||||||
|
@ConfigurePigeon(
|
||||||
|
PigeonOptions(
|
||||||
|
dartOut: 'lib/src/pigeons/proxy.g.dart',
|
||||||
|
dartOptions: DartOptions(),
|
||||||
|
kotlinOut:
|
||||||
|
'android/src/main/kotlin/eu/weblibre/pluggable_transports_proxy/pigeons/Proxy.g.kt',
|
||||||
|
kotlinOptions: KotlinOptions(
|
||||||
|
package: 'eu.weblibre.pluggable_transports_proxy.pigeons',
|
||||||
|
),
|
||||||
|
dartPackageName: 'pluggable_transports_proxy',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
@HostApi()
|
||||||
|
abstract class IPtProxyController {
|
||||||
|
int start(ProxyType proxyType, String proxy);
|
||||||
|
void stop(ProxyType proxyType);
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
name: pluggable_transports_proxy
|
||||||
|
description: "A new Flutter plugin project."
|
||||||
|
version: 0.0.1
|
||||||
|
publish_to: 'none'
|
||||||
|
resolution: workspace
|
||||||
|
|
||||||
|
environment:
|
||||||
|
sdk: ^3.9.0
|
||||||
|
flutter: '>=3.3.0'
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
|
||||||
|
dev_dependencies:
|
||||||
|
flutter_test:
|
||||||
|
sdk: flutter
|
||||||
|
lint: ^2.8.0
|
||||||
|
pigeon: ^26.0.1
|
||||||
|
|
||||||
|
# For information on the generic Dart part of this file, see the
|
||||||
|
# following page: https://dart.dev/tools/pub/pubspec
|
||||||
|
|
||||||
|
# The following section is specific to Flutter packages.
|
||||||
|
flutter:
|
||||||
|
# This section identifies this Flutter project as a plugin project.
|
||||||
|
# The 'pluginClass' specifies the class (in Java, Kotlin, Swift, Objective-C, etc.)
|
||||||
|
# which should be registered in the plugin registry. This is required for
|
||||||
|
# using method channels.
|
||||||
|
# The Android 'package' specifies package in which the registered class is.
|
||||||
|
# This is required for using method channels on Android.
|
||||||
|
# The 'ffiPlugin' specifies that native code should be built and bundled.
|
||||||
|
# This is required for using `dart:ffi`.
|
||||||
|
# All these are used by the tooling to maintain consistency when
|
||||||
|
# adding or updating assets for this project.
|
||||||
|
plugin:
|
||||||
|
platforms:
|
||||||
|
android:
|
||||||
|
package: eu.weblibre.pluggable_transports_proxy
|
||||||
|
pluginClass: PluggableTransportsProxyPlugin
|
||||||
|
|
||||||
|
# To add assets to your plugin package, add an assets section, like this:
|
||||||
|
# assets:
|
||||||
|
# - images/a_dot_burr.jpeg
|
||||||
|
# - images/a_dot_ham.jpeg
|
||||||
|
#
|
||||||
|
# For details regarding assets in packages, see
|
||||||
|
# https://flutter.dev/to/asset-from-package
|
||||||
|
#
|
||||||
|
# An image asset can refer to one or more resolution-specific "variants", see
|
||||||
|
# https://flutter.dev/to/resolution-aware-images
|
||||||
|
|
||||||
|
# To add custom fonts to your plugin package, add a fonts section here,
|
||||||
|
# in this "flutter" section. Each entry in this list should have a
|
||||||
|
# "family" key with the font family name, and a "fonts" key with a
|
||||||
|
# list giving the asset and other descriptors for the font. For
|
||||||
|
# example:
|
||||||
|
# fonts:
|
||||||
|
# - family: Schyler
|
||||||
|
# fonts:
|
||||||
|
# - asset: fonts/Schyler-Regular.ttf
|
||||||
|
# - asset: fonts/Schyler-Italic.ttf
|
||||||
|
# style: italic
|
||||||
|
# - family: Trajan Pro
|
||||||
|
# fonts:
|
||||||
|
# - asset: fonts/TrajanPro.ttf
|
||||||
|
# - asset: fonts/TrajanPro_Bold.ttf
|
||||||
|
# weight: 700
|
||||||
|
#
|
||||||
|
# For details regarding fonts in packages, see
|
||||||
|
# https://flutter.dev/to/font-from-package
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
// Autogenerated from Pigeon (v26.0.0), do not edit directly.
|
// Autogenerated from Pigeon (v26.0.1), do not edit directly.
|
||||||
// See also: https://pub.dev/packages/pigeon
|
// See also: https://pub.dev/packages/pigeon
|
||||||
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
|
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Autogenerated from Pigeon (v26.0.0), do not edit directly.
|
// Autogenerated from Pigeon (v26.0.1), do not edit directly.
|
||||||
// See also: https://pub.dev/packages/pigeon
|
// See also: https://pub.dev/packages/pigeon
|
||||||
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers
|
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ workspace:
|
|||||||
- app/
|
- app/
|
||||||
- packages/flutter_mozilla_components
|
- packages/flutter_mozilla_components
|
||||||
- packages/flutter_mozilla_components/example
|
- packages/flutter_mozilla_components/example
|
||||||
|
- packages/pluggable_transports_proxy
|
||||||
- packages/simple_intent_receiver
|
- packages/simple_intent_receiver
|
||||||
- packages/simple_intent_receiver/example
|
- packages/simple_intent_receiver/example
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
|||||||
Reference in New Issue
Block a user