This commit is contained in:
problematicconsumer
2023-07-06 17:18:41 +03:30
commit b617c95f62
352 changed files with 21017 additions and 0 deletions

53
.gitignore vendored Normal file
View File

@@ -0,0 +1,53 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
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
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/
# generated files
**/*.g.dart
**/*.freezed.dart
**/*.gen.dart
**/libclash.so
**/libclash.h
**/*.dll
**/*.dylib
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release

45
.metadata Normal file
View File

@@ -0,0 +1,45 @@
# 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.
version:
revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
channel: stable
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
base_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
- platform: android
create_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
base_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
- platform: ios
create_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
base_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
- platform: linux
create_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
base_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
- platform: macos
create_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
base_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
- platform: web
create_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
base_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
- platform: windows
create_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
base_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
# 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'

27
Makefile Normal file
View File

@@ -0,0 +1,27 @@
ANDROID_OUT=../android/app/src/main/jniLibs
NDK_BIN=$(ANDROID_HOME)/ndk/25.2.9519653/toolchains/llvm/prebuilt/linux-x86_64/bin
GOBUILD=CGO_ENABLED=1 go build -trimpath -tags with_gvisor,with_lwip -ldflags="-w -s" -buildmode=c-shared
get:
dart pub get
gen:
dart run build_runner build --delete-conflicting-outputs
translate:
dart run slang
android-libs: android-x64 android-arm android-arm64
android-x64:
cd core && env GOOS=android GOARCH=amd64 CC=$(NDK_BIN)/x86_64-linux-android21-clang $(GOBUILD) -o $(ANDROID_OUT)/x86_64/libclash.so # building android x64 clash libs
android-arm:
cd core && env GOOS=android GOARCH=arm GOARM=7 CC=$(NDK_BIN)/armv7a-linux-androideabi21-clang $(GOBUILD) -o $(ANDROID_OUT)/armeabi-v7a/libclash.so # building android arm clash libs
android-arm64:
cd core && env GOOS=android GOARCH=arm64 CC=$(NDK_BIN)/aarch64-linux-android21-clang $(GOBUILD) -o $(ANDROID_OUT)/arm64-v8a/libclash.so # building android arm64 clash libs
windows-libs:
cd core && env GOOS=windows GOARCH=amd64 CC=x86_64-w64-mingw32-gcc $(GOBUILD) -o dist/libclash.dll # building windows clash libs
release-android: get gen
flutter build apk --target-platform android-arm,android-arm64,android-x64 --split-per-abi

33
README.md Normal file
View File

@@ -0,0 +1,33 @@
# Hiddify Next
<p align="center"><img src="assets/images/logo.svg" width="168"/></p>
<p align="center" style="font-size: 20px">Multi-platform Proxy Frontend</p>
<p align="center" style="font-size: 20px">⚠Hiddify Next is still in early development phase⚠</p>
<p align="center" style="font-size: 16px">Windows and Android supported (more platforms coming soon)</p>
## Build from source
### requirements:
- GO v1.19+
- Flutter v3.10+
- Make
- GCC
- MinGW-w64
- Android SDK (with CMake and NDK)
```shell
# fetch dependencies and build generated files
$ make get gen
# build clash native library for all supported platforms and architectures
$ make android-libs windows-libs
# build apk for android
$ make release-android
```
## Acknowledgements
- [Clash](https://github.com/Dreamacro/clash)
- [Clash Meta](https://github.com/MetaCubeX/Clash.Meta)
- [FClash](https://github.com/Fclash/Fclash)

21
analysis_options.yaml Normal file
View File

@@ -0,0 +1,21 @@
include: package:lint/strict.yaml
analyzer:
plugins:
- custom_lint
exclude:
- "**.g.dart"
- "lib/gen/**"
errors:
invalid_annotation_target: ignore
linter:
rules:
sort_pub_dependencies: false
sort_unnamed_constructors_first: false
avoid_classes_with_only_static_members: false
custom_lint:
rules:
# Enable one rule
- provider_parameters

13
android/.gitignore vendored Normal file
View File

@@ -0,0 +1,13 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties
**/*.keystore
**/*.jks

74
android/app/build.gradle Normal file
View File

@@ -0,0 +1,74 @@
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
namespace "com.hiddify.hiddify"
compileSdkVersion flutter.compileSdkVersion
ndkVersion flutter.ndkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.hiddify.hiddify"
minSdkVersion 21
targetSdkVersion 33
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
multiDexEnabled true
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
}
flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
implementation 'androidx.window:window:1.0.0'
implementation 'androidx.window:window-java:1.0.0'
}

View File

@@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

View File

@@ -0,0 +1,57 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<application
android:label="hiddify"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="clash" />
<data android:scheme="clashmeta" />
<data android:host="install-config"/>
</intent-filter>
</activity>
<service
android:name=".HiddifyVpnService"
android:permission="android.permission.BIND_VPN_SERVICE"
android:stopWithTask="false"
android:exported="false">
<intent-filter>
<action android:name="android.net.VpnService"/>
</intent-filter>
</service>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,317 @@
package com.hiddify.hiddify
import android.app.PendingIntent
import android.app.Service
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.ConnectivityManager
import android.net.LocalSocket
import android.net.LocalSocketAddress
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
import android.net.ProxyInfo
import android.net.VpnService
import android.os.Build
import android.os.ParcelFileDescriptor
import android.os.StrictMode
import android.util.Log
import androidx.annotation.RequiresApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.io.File
import java.lang.ref.SoftReference
class HiddifyVpnService : VpnService() {
companion object {
const val TAG = "Hiddify/VpnService"
const val EVENT_TAG = "Hiddify/VpnServiceEvents"
private const val TUN2SOCKS = "libtun2socks.so"
private const val TUN_MTU = 9000
private const val TUN_GATEWAY = "172.19.0.1"
private const val TUN_ROUTER = "172.19.0.2"
private const val TUN_SUBNET_PREFIX = 30
private const val NET_ANY = "0.0.0.0"
private val HTTP_PROXY_LOCAL_LIST = listOf(
"localhost",
"*.local",
"127.*",
"10.*",
"172.16.*",
"172.17.*",
"172.18.*",
"172.19.*",
"172.2*",
"172.30.*",
"172.31.*",
"192.168.*"
)
}
private var vpnBroadcastReceiver: VpnState? = null
private var conn: ParcelFileDescriptor? = null
private lateinit var process: Process
private var isRunning = false
// prefs
private var includeAppPackages: Set<String> = HashSet()
fun getService(): Service {
return this
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
startVpnService()
return START_STICKY
}
override fun onCreate() {
super.onCreate()
Log.d(TAG, "creating vpn service")
val policy = StrictMode.ThreadPolicy.Builder().permitAll().build()
StrictMode.setThreadPolicy(policy)
registerBroadcastReceiver()
VpnServiceManager.vpnService = SoftReference(this)
}
override fun onRevoke() {
Log.d(TAG, "vpn service revoked")
super.onRevoke()
stopVpnService()
}
override fun onDestroy() {
Log.d(TAG, "vpn service destroyed")
super.onDestroy()
broadcastVpnStatus(false)
VpnServiceManager.cancelNotification()
unregisterBroadcastReceiver()
}
private fun registerBroadcastReceiver() {
Log.d(TAG, "registering receiver in service")
vpnBroadcastReceiver = VpnState()
val intentFilter = IntentFilter(VpnState.ACTION_VPN_STATUS)
registerReceiver(vpnBroadcastReceiver, intentFilter)
}
private fun unregisterBroadcastReceiver() {
Log.d(TAG, "unregistering receiver in service")
if (vpnBroadcastReceiver != null) {
unregisterReceiver(vpnBroadcastReceiver)
vpnBroadcastReceiver = null
}
}
private fun broadcastVpnStatus(isVpnActive: Boolean) {
Log.d(TAG, "broadcasting status= $isVpnActive")
val intent = Intent(VpnState.ACTION_VPN_STATUS)
intent.putExtra(VpnState.IS_VPN_ACTIVE, isVpnActive)
sendBroadcast(intent)
}
@delegate:RequiresApi(Build.VERSION_CODES.P)
private val defaultNetworkRequest by lazy {
NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
.build()
}
private val connectivity by lazy { getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager }
@delegate:RequiresApi(Build.VERSION_CODES.P)
private val defaultNetworkCallback by lazy {
object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
setUnderlyingNetworks(arrayOf(network))
}
override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {
// it's a good idea to refresh capabilities
setUnderlyingNetworks(arrayOf(network))
}
override fun onLost(network: Network) {
setUnderlyingNetworks(null)
}
}
}
private fun startVpnService() {
val prepare = prepare(this)
if (prepare != null) {
return
}
with(Builder()) {
addAddress(TUN_GATEWAY, TUN_SUBNET_PREFIX)
setMtu(TUN_MTU)
addRoute(NET_ANY, 0)
addDnsServer(TUN_ROUTER)
allowBypass()
setBlocking(true)
setSession("Hiddify")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
setMetered(false)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && VpnServiceManager.prefs.systemProxy) {
setHttpProxy(
ProxyInfo.buildDirectProxy(
"127.0.0.1",
VpnServiceManager.prefs.httpPort,
HTTP_PROXY_LOCAL_LIST,
)
)
}
if (includeAppPackages.isEmpty()) {
addDisallowedApplication(packageName)
} else {
includeAppPackages.forEach {
addAllowedApplication(it)
}
}
setConfigureIntent(
PendingIntent.getActivity(
this@HiddifyVpnService,
0,
Intent().setComponent(ComponentName(packageName, "$packageName.MainActivity")),
pendingIntentFlags(PendingIntent.FLAG_UPDATE_CURRENT)
)
)
try {
conn?.close()
} catch (ignored: Exception) {
// ignored
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
try {
connectivity.requestNetwork(defaultNetworkRequest, defaultNetworkCallback)
} catch (e: Exception) {
e.printStackTrace()
}
}
try {
conn = establish()
isRunning = true
runTun2socks()
VpnServiceManager.showNotification()
Log.d(TAG, "vpn connection established")
broadcastVpnStatus(true)
} catch (e: Exception) {
Log.w(TAG, "failed to start vpn service: $e")
e.printStackTrace()
stopVpnService()
broadcastVpnStatus(false)
}
}
}
fun stopVpnService(isForced: Boolean = true) {
Log.d(TAG, "stopping vpn service, forced: [$isForced]")
isRunning = false
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
try {
connectivity.unregisterNetworkCallback(defaultNetworkCallback)
} catch (ignored: Exception) {
// ignored
}
}
try {
Log.d(TAG, "destroying tun2socks")
process.destroy()
} catch (e: Exception) {
Log.e(TAG, e.toString())
}
if(isForced) {
stopSelf()
try {
conn?.close()
conn = null
} catch (ignored: Exception) {
// ignored
}
}
Log.d(TAG, "vpn service stopped")
}
private fun runTun2socks() {
val cmd = arrayListOf(
File(applicationContext.applicationInfo.nativeLibraryDir, TUN2SOCKS).absolutePath,
"--netif-ipaddr", TUN_ROUTER,
"--netif-netmask", "255.255.255.252",
"--socks-server-addr", "127.0.0.1:${VpnServiceManager.prefs.socksPort}",
"--tunmtu", TUN_MTU.toString(),
"--sock-path", "sock_path",//File(applicationContext.filesDir, "sock_path").absolutePath,
"--enable-udprelay",
"--loglevel", "notice")
Log.d(TAG, cmd.toString())
protect(conn!!.fd) // not sure
try {
val proBuilder = ProcessBuilder(cmd)
proBuilder.redirectErrorStream(true)
process = proBuilder
.directory(applicationContext.filesDir)
.start()
Thread(Runnable {
Log.d(TAG,"$TUN2SOCKS check")
process.waitFor()
Log.d(TAG,"$TUN2SOCKS exited")
if (isRunning) {
Log.d(packageName,"$TUN2SOCKS restart")
runTun2socks()
}
}).start()
Log.d(TAG, process.toString())
sendFd()
} catch (e: Exception) {
Log.d(TAG, e.toString())
}
}
private fun sendFd() {
val fd = conn!!.fileDescriptor
val path = File(applicationContext.filesDir, "sock_path").absolutePath
Log.d(TAG, path)
GlobalScope.launch(Dispatchers.IO) {
var tries = 0
while (true) try {
Thread.sleep(50L shl tries)
Log.d(TAG, "sendFd tries: $tries")
LocalSocket().use { localSocket ->
localSocket.connect(LocalSocketAddress(path, LocalSocketAddress.Namespace.FILESYSTEM))
localSocket.setFileDescriptorsForSend(arrayOf(fd))
localSocket.outputStream.write(42)
}
break
} catch (e: Exception) {
Log.d(TAG, e.toString())
if (tries > 5) break
tries += 1
}
}
}
private fun pendingIntentFlags(flags: Int, mutable: Boolean = false): Int {
return if (Build.VERSION.SDK_INT >= 24) {
if (Build.VERSION.SDK_INT > 30 && mutable) {
flags or PendingIntent.FLAG_MUTABLE
} else {
flags or PendingIntent.FLAG_IMMUTABLE
}
} else {
flags
}
}
}

View File

@@ -0,0 +1,116 @@
package com.hiddify.hiddify
import android.content.Intent
import android.content.IntentFilter
import android.net.VpnService
import android.util.Log
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.EventChannel
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
class MainActivity : FlutterActivity(), MethodChannel.MethodCallHandler {
private lateinit var methodChannel: MethodChannel
private lateinit var eventChannel: EventChannel
private lateinit var methodResult: MethodChannel.Result
private var vpnBroadcastReceiver: VpnState? = null
companion object {
const val VPN_PERMISSION_REQUEST_CODE = 1001
enum class Action(val method: String) {
GrantPermission("grant_permission"),
StartProxy("start"),
StopProxy("stop"),
RefreshStatus("refresh_status"),
SetPrefs("set_prefs")
}
}
private fun registerBroadcastReceiver() {
Log.d(HiddifyVpnService.TAG, "registering broadcast receiver")
vpnBroadcastReceiver = VpnState()
val intentFilter = IntentFilter(VpnState.ACTION_VPN_STATUS)
registerReceiver(vpnBroadcastReceiver, intentFilter)
}
private fun unregisterBroadcastReceiver() {
Log.d(HiddifyVpnService.TAG, "unregistering broadcast receiver")
if (vpnBroadcastReceiver != null) {
unregisterReceiver(vpnBroadcastReceiver)
vpnBroadcastReceiver = null
}
}
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
methodChannel =
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, HiddifyVpnService.TAG)
methodChannel.setMethodCallHandler(this)
eventChannel = EventChannel(flutterEngine.dartExecutor.binaryMessenger, HiddifyVpnService.EVENT_TAG)
registerBroadcastReceiver()
eventChannel.setStreamHandler(vpnBroadcastReceiver)
}
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
methodResult = result
@Suppress("UNCHECKED_CAST")
when (call.method) {
Action.GrantPermission.method -> {
grantVpnPermission()
}
Action.StartProxy.method -> {
VpnServiceManager.startVpnService(this)
result.success(true)
}
Action.StopProxy.method -> {
VpnServiceManager.stopVpnService()
result.success(true)
}
Action.RefreshStatus.method -> {
val statusIntent = Intent(VpnState.ACTION_VPN_STATUS)
statusIntent.putExtra(VpnState.IS_VPN_ACTIVE, VpnServiceManager.isRunning)
sendBroadcast(statusIntent)
result.success(true)
}
Action.SetPrefs.method -> {
val args = call.arguments as Map<String, Any>
VpnServiceManager.setPrefs(context, args)
result.success(true)
}
else -> {
result.notImplemented()
}
}
}
override fun onDestroy() {
super.onDestroy()
unregisterBroadcastReceiver()
}
private fun grantVpnPermission() {
val vpnPermissionIntent = VpnService.prepare(this)
if (vpnPermissionIntent == null) {
onActivityResult(VPN_PERMISSION_REQUEST_CODE, RESULT_OK, null)
} else {
startActivityForResult(vpnPermissionIntent, VPN_PERMISSION_REQUEST_CODE)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == VPN_PERMISSION_REQUEST_CODE) {
methodResult.success(resultCode == RESULT_OK)
} else if (requestCode == 101010) {
methodResult.success(resultCode == RESULT_OK)
}
}
}

View File

@@ -0,0 +1,97 @@
package com.hiddify.hiddify
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.content.Context.NOTIFICATION_SERVICE
import android.content.Intent
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import java.lang.ref.SoftReference
data class VpnServiceConfigs(val httpPort: Int = 12346, val socksPort: Int = 12347, val systemProxy: Boolean = true)
object VpnServiceManager {
private const val NOTIFICATION_ID = 1
private const val NOTIFICATION_CHANNEL_ID = "hiddify_vpn"
private const val NOTIFICATION_CHANNEL_NAME = "Hiddify VPN"
var vpnService: SoftReference<HiddifyVpnService>? = null
var prefs = VpnServiceConfigs()
var isRunning = false
private var mBuilder: NotificationCompat.Builder? = null
private var mNotificationManager: NotificationManager? = null
fun startVpnService(context: Context) {
val intent = Intent(context.applicationContext, HiddifyVpnService::class.java)
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) {
context.startForegroundService(intent)
} else {
context.startService(intent)
}
}
fun stopVpnService() {
val service = vpnService?.get() ?: return
service.stopVpnService()
}
fun setPrefs(context: Context,args: Map<String, Any>) {
prefs = prefs.copy(
httpPort = args["httpPort"] as Int? ?: prefs.httpPort,
socksPort = args["socksPort"] as Int? ?: prefs.socksPort,
systemProxy = args["systemProxy"] as Boolean? ?: prefs.systemProxy,
)
if(isRunning) {
stopVpnService()
startVpnService(context)
}
}
fun showNotification() {
val service = vpnService?.get()?.getService() ?: return
val channelId = if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotificationChannel()
} else {
""
}
mBuilder = NotificationCompat.Builder(service, channelId)
.setSmallIcon(R.drawable.ic_stat_logo)
.setPriority(NotificationCompat.PRIORITY_MIN)
.setOngoing(true)
.setShowWhen(false)
.setOnlyAlertOnce(true)
.setContentTitle("Hiddify")
.setContentText("Connected")
service.startForeground(NOTIFICATION_ID, mBuilder?.build())
}
fun cancelNotification() {
val service = vpnService?.get()?.getService() ?: return
service.stopForeground(true)
mBuilder = null
}
@RequiresApi(Build.VERSION_CODES.O)
private fun createNotificationChannel(): String {
val channel = NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH)
channel.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
getNotificationManager()?.createNotificationChannel(
channel
)
return NOTIFICATION_CHANNEL_ID
}
private fun getNotificationManager(): NotificationManager? {
if (mNotificationManager == null) {
val service = vpnService?.get()?.getService() ?: return null
mNotificationManager = service.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
}
return mNotificationManager
}
}

View File

@@ -0,0 +1,34 @@
package com.hiddify.hiddify
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.util.Log
import io.flutter.plugin.common.EventChannel
class VpnState : BroadcastReceiver(), EventChannel.StreamHandler{
companion object {
const val ACTION_VPN_STATUS = "Hiddify.VpnState.ACTION_VPN_STATUS"
const val IS_VPN_ACTIVE = "isVpnActive"
}
private var eventSink: EventChannel.EventSink? = null
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
eventSink = events
}
override fun onCancel(arguments: Any?) {
eventSink = null
}
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == ACTION_VPN_STATUS) {
val isVpnActive = intent.getBooleanExtra(IS_VPN_ACTIVE, false)
Log.d(HiddifyVpnService.TAG, "send to flutter: status= $isVpnActive")
VpnServiceManager.isRunning = isVpnActive
eventSink?.success(isVpnActive)
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 557 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 815 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 B

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<bitmap android:gravity="fill" android:src="@drawable/background"/>
</item>
<item>
<bitmap android:gravity="center" android:src="@drawable/splash"/>
</item>
</layer-list>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 B

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<bitmap android:gravity="fill" android:src="@drawable/background"/>
</item>
<item>
<bitmap android:gravity="center" android:src="@drawable/splash"/>
</item>
</layer-list>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@mipmap/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
<monochrome android:drawable="@mipmap/ic_launcher_monochrome"/>
</adaptive-icon>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@mipmap/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
<monochrome android:drawable="@mipmap/ic_launcher_monochrome"/>
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 768 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 548 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 956 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 682 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1019 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:forceDarkAllowed">false</item>
<item name="android:windowFullscreen">false</item>
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
<item name="android:windowSplashScreenBackground">#ffffff</item>
<item name="android:windowSplashScreenAnimatedIcon">@drawable/android12splash</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
<item name="android:forceDarkAllowed">false</item>
<item name="android:windowFullscreen">false</item>
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:forceDarkAllowed">false</item>
<item name="android:windowFullscreen">false</item>
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
<item name="android:windowSplashScreenBackground">#ffffff</item>
<item name="android:windowSplashScreenAnimatedIcon">@drawable/android12splash</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- exclude 127.0.0.0/8 169.254.0.0/16 10.0.0.0/8 192.168.0.0/16 172.16.0.0/12 -->
<string-array name="bypass_private_route" translatable="false">
<item>1.0.0.0/8</item>
<item>2.0.0.0/7</item>
<item>4.0.0.0/6</item>
<item>8.0.0.0/7</item>
<item>11.0.0.0/8</item>
<item>12.0.0.0/6</item>
<item>16.0.0.0/4</item>
<item>32.0.0.0/3</item>
<item>64.0.0.0/3</item>
<item>96.0.0.0/4</item>
<item>112.0.0.0/5</item>
<item>120.0.0.0/6</item>
<item>124.0.0.0/7</item>
<item>126.0.0.0/8</item>
<item>128.0.0.0/3</item>
<item>160.0.0.0/5</item>
<item>168.0.0.0/8</item>
<item>169.0.0.0/9</item>
<item>169.128.0.0/10</item>
<item>169.192.0.0/11</item>
<item>169.224.0.0/12</item>
<item>169.240.0.0/13</item>
<item>169.248.0.0/14</item>
<item>169.252.0.0/15</item>
<item>169.255.0.0/16</item>
<item>170.0.0.0/7</item>
<item>172.0.0.0/12</item>
<item>172.32.0.0/11</item>
<item>172.64.0.0/10</item>
<item>172.128.0.0/9</item>
<item>173.0.0.0/8</item>
<item>174.0.0.0/7</item>
<item>176.0.0.0/4</item>
<item>192.0.0.0/9</item>
<item>192.128.0.0/11</item>
<item>192.160.0.0/13</item>
<item>192.169.0.0/16</item>
<item>192.170.0.0/15</item>
<item>192.172.0.0/14</item>
<item>192.176.0.0/12</item>
<item>192.192.0.0/10</item>
<item>193.0.0.0/8</item>
<item>194.0.0.0/7</item>
<item>196.0.0.0/6</item>
<item>200.0.0.0/5</item>
<item>208.0.0.0/4</item>
<item>240.0.0.0/5</item>
<item>248.0.0.0/6</item>
<item>252.0.0.0/7</item>
<item>254.0.0.0/8</item>
<item>255.0.0.0/9</item>
<item>255.128.0.0/10</item>
<item>255.192.0.0/11</item>
<item>255.224.0.0/12</item>
<item>255.240.0.0/13</item>
<item>255.248.0.0/14</item>
<item>255.252.0.0/15</item>
<item>255.254.0.0/16</item>
<item>255.255.0.0/17</item>
<item>255.255.128.0/18</item>
<item>255.255.192.0/19</item>
<item>255.255.224.0/20</item>
<item>255.255.240.0/21</item>
<item>255.255.248.0/22</item>
<item>255.255.252.0/23</item>
<item>255.255.254.0/24</item>
<item>255.255.255.0/25</item>
<item>255.255.255.128/26</item>
<item>255.255.255.192/27</item>
<item>255.255.255.224/28</item>
<item>255.255.255.240/29</item>
<item>255.255.255.248/30</item>
<item>255.255.255.252/31</item>
<item>255.255.255.254/32</item>
</string-array>
</resources>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
<item name="android:forceDarkAllowed">false</item>
<item name="android:windowFullscreen">false</item>
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

31
android/build.gradle Normal file
View File

@@ -0,0 +1,31 @@
buildscript {
ext.kotlin_version = '1.7.10'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.3.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
tasks.register("clean", Delete) {
delete rootProject.buildDir
}

View File

@@ -0,0 +1,3 @@
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true

View File

@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip

11
android/settings.gradle Normal file
View File

@@ -0,0 +1,11 @@
include ':app'
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
def properties = new Properties()
assert localPropertiesFile.exists()
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"

Binary file not shown.

View File

@@ -0,0 +1,16 @@
external-controller: 127.0.0.1:22345
mixed-port: 22346
rules:
# localhost rule
- DOMAIN-KEYWORD,announce,DIRECT
- DOMAIN-KEYWORD,torrent,DIRECT
- DOMAIN-KEYWORD,tracker,DIRECT
- DOMAIN-SUFFIX,smtp,DIRECT
- DOMAIN-SUFFIX,local,DIRECT
- IP-CIDR,192.168.0.0/16,DIRECT
- IP-CIDR,10.0.0.0/8,DIRECT
- IP-CIDR,172.16.0.0/12,DIRECT
- IP-CIDR,127.0.0.0/8,DIRECT
- IP-CIDR,100.64.0.0/10,DIRECT

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

7
assets/images/logo.svg Normal file
View File

@@ -0,0 +1,7 @@
<svg width="400" height="400" viewBox="0 0 19 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14 3.28347C14 3.10785 14.0921 2.9451 14.2427 2.85474L18.2427 0.454423C18.576 0.25444 19 0.494494 19 0.883154V5C19 5.27614 18.7761 5.5 18.5 5.5H14.5C14.2239 5.5 14 5.27614 14 5V3.28347Z" fill="#455FE9"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M7 7.28365C7 7.10803 7.09214 6.94529 7.24273 6.85492L11.2427 4.45461C11.576 4.25463 12 4.49468 12 4.88334V12.0006V12.5006V17.0006C12 17.2767 11.7761 17.5006 11.5 17.5006H7.5C7.22386 17.5006 7 17.2767 7 17.0006V12.5006V12.0006V7.28365ZM0.242727 11.3549C0.0921388 11.4453 0 11.608 0 11.7837V17.0006C0 17.2767 0.223858 17.5006 0.5 17.5006H4.5C4.77614 17.5006 5 17.2767 5 17.0006V9.38334C5 8.99468 4.57599 8.75463 4.24273 8.95461L0.242727 11.3549Z" fill="#455FE9"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 12.5005H2V16.5005H5V15.5005C5 15.2243 5.22386 15.0005 5.5 15.0005H6.5C6.77614 15.0005 7 15.2243 7 15.5005V16.5005H11V12.5005H7V13.5C7 13.7761 6.77614 14 6.5 14H5.5C5.22386 14 5 13.7761 5 13.5V12.5005Z" fill="#455FE9"/>
<rect x="14" y="17.5005" width="11" height="5" rx="0.5" transform="rotate(-90 14 17.5005)" fill="#455FE9"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

View File

@@ -0,0 +1,125 @@
{
"general": {
"appTitle": "hiddify",
"reset": "reset",
"toggle": {
"enabled": "enabled",
"disabled": "disabled"
}
},
"home": {
"pageTitle": "home",
"emptyProfilesMsg": "start by adding subscription profile",
"noActiveProfileMsg": "select a profile",
"connection": {
"tapToConnect": "tap to connect",
"connecting": "connecting",
"disconnecting": "disconnecting",
"connected": "connected"
}
},
"profile": {
"overviewPageTitle": "profiles",
"detailsPageTitle": "profile",
"subscription": {
"traffic": "traffic",
"updatedTimeAgo": "updated ${timeago}",
"remaining": "remaining",
"expired": "expired",
"noTraffic": "no traffic"
},
"add": {
"buttonText": "add new profile",
"fromClipboard": "add from clipboard",
"scanQr": "Scan QR code",
"manually": "add manually",
"invalidUrlMsg": "unexpected url"
},
"update": {
"failureMsg": "failed to update profile: ${reason}",
"successMsg": "successfully updated profile"
},
"delete": {
"buttonText": "delete",
"confirmationMsg": "delete profile for ever? this can not be undone",
"successMsg": "successfully deleted profile"
},
"save": {
"buttonText": "save",
"successMsg": "successfully saved profile"
},
"detailsForm": {
"nameHint": "name",
"urlHint": "url",
"emptyNameMsg": "name can't be empty",
"invalidUrlMsg": "invalid URL"
}
},
"proxies": {
"pageTitle": "proxies",
"emptyProxiesMsg": "no proxies",
"delayTestTooltip": "delay test",
"cancelTestButtonText": "cancel test"
},
"logs": {
"pageTitle": "logs",
"clearLogsButtonText": "clear",
"filterHint": "filter",
"allLevelsFilter": "all"
},
"settings": {
"pageTitle": "settings",
"appearance": {
"sectionTitle": "appearance",
"themeMode": "theme mode",
"themeModes": {
"system": "follow system theme",
"dark": "dark mode",
"light": "light mode"
},
"trueBlack": "true black"
},
"network": {
"sectionTitle": "network",
"systemProxy": "system proxy",
"systemProxyMsg": "Attach http proxy to VpnService",
"bypassPrivateNetworks": "bypass private networks",
"bypassPrivateNetworksMsg": "Bypass private network addresses"
},
"clash": {
"sectionTitle": "clash proxy overrides",
"doNotModify": "do not modify",
"overrides": {
"httpPort": "HTTP Port",
"socksPort": "Socks Port",
"redirPort": "Redirect Port",
"tproxyPort": "TProxy Port",
"mixedPort": "Mixed Port",
"allowLan": "Allow LAN",
"ipv6": "IPv6",
"mode": "Mode",
"logLevel": "Log Level"
}
}
},
"tray": {
"dashboard": "dashboard",
"quit": "quit",
"systemProxy": "system proxy"
},
"failure": {
"unexpected": "unexpected failure",
"clash": {
"unexpected": "unexpected failure",
"core": "clash failure ${reason}"
},
"connectivity": {
"unexpected": "unexpected failure"
},
"profiles": {
"unexpected": "unexpected failure",
"notFound": "profile not found",
"invalidConfig": "invalid config"
}
}
}

17
build.yaml Normal file
View File

@@ -0,0 +1,17 @@
targets:
$default:
builders:
drift_dev:
generate_for:
- "lib/data/local/**"
options:
store_date_time_values_as_text: true
slang_build_runner:
options:
base_locale: en
input_directory: assets/translations
input_file_pattern: .i18n.json
output_directory: lib/gen
output_file_name: translations.g.dart
translation_class_visibility: public
locale_handling: false

View File

@@ -0,0 +1,23 @@
# Copyright (c) 2021, 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.
import("../../sdk_args.gni")
# This rule copies header files to include/
copy("copy_headers") {
visibility = [ "../../sdk:copy_headers" ]
sources = [
"dart_api.h",
"dart_api_dl.c",
"dart_api_dl.h",
"dart_native_api.h",
"dart_tools_api.h",
"dart_version.h",
"internal/dart_api_dl_impl.h",
]
outputs =
[ "$root_out_dir/$dart_sdk_output/include/{{source_target_relative}}" ]
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (c) 2021, 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.
*/
#ifndef RUNTIME_INCLUDE_ANALYZE_SNAPSHOT_API_H_
#define RUNTIME_INCLUDE_ANALYZE_SNAPSHOT_API_H_
#include <stdint.h>
namespace dart {
namespace snapshot_analyzer {
typedef struct {
const uint8_t* vm_snapshot_data;
const uint8_t* vm_snapshot_instructions;
const uint8_t* vm_isolate_data;
const uint8_t* vm_isolate_instructions;
} Dart_SnapshotAnalyzerInformation;
void Dart_DumpSnapshotInformationAsJson(char** buffer,
intptr_t* buffer_length,
Dart_SnapshotAnalyzerInformation* info);
void Dart_DumpSnapshotInformationPP(Dart_SnapshotAnalyzerInformation* info);
} // namespace snapshot_analyzer
} // namespace dart
#endif // RUNTIME_INCLUDE_ANALYZE_SNAPSHOT_API_H_

View File

@@ -0,0 +1,69 @@
// Copyright (c) 2015, 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.
#ifndef RUNTIME_INCLUDE_BIN_DART_IO_API_H_
#define RUNTIME_INCLUDE_BIN_DART_IO_API_H_
#include "dart_tools_api.h"
namespace dart {
namespace bin {
// Bootstraps 'dart:io'.
void BootstrapDartIo();
// Cleans up 'dart:io'.
void CleanupDartIo();
// Lets dart:io know where the system temporary directory is located.
// Currently only wired up on Android.
void SetSystemTempDirectory(const char* system_temp);
// Tells the system whether to capture Stdout events.
void SetCaptureStdout(bool value);
// Tells the system whether to capture Stderr events.
void SetCaptureStderr(bool value);
// Should Stdout events be captured?
bool ShouldCaptureStdout();
// Should Stderr events be captured?
bool ShouldCaptureStderr();
// Set the executable name used by Platform.executable.
void SetExecutableName(const char* executable_name);
// Set the arguments used by Platform.executableArguments.
void SetExecutableArguments(int script_index, char** argv);
// Set dart:io implementation specific fields of Dart_EmbedderInformation.
void GetIOEmbedderInformation(Dart_EmbedderInformation* info);
// Appropriate to assign to Dart_InitializeParams.file_open/read/write/close.
void* OpenFile(const char* name, bool write);
void ReadFile(uint8_t** data, intptr_t* file_len, void* stream);
void WriteFile(const void* buffer, intptr_t num_bytes, void* stream);
void CloseFile(void* stream);
// Generates 'length' random bytes into 'buffer'. Returns true on success
// and false on failure. This is appropriate to assign to
// Dart_InitializeParams.entropy_source.
bool GetEntropy(uint8_t* buffer, intptr_t length);
// Performs a lookup of the I/O Dart_NativeFunction with a specified 'name' and
// 'argument_count'. Returns NULL if no I/O native function with a matching
// name and parameter count is found.
Dart_NativeFunction LookupIONative(Dart_Handle name,
int argument_count,
bool* auto_setup_scope);
// Returns the symbol for I/O native function 'nf'. Returns NULL if 'nf' is not
// a valid I/O native function.
const uint8_t* LookupIONativeSymbol(Dart_NativeFunction nf);
} // namespace bin
} // namespace dart
#endif // RUNTIME_INCLUDE_BIN_DART_IO_API_H_

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2020, 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.
*/
#include "dart_api_dl.h" /* NOLINT */
#include "dart_version.h" /* NOLINT */
#include "internal/dart_api_dl_impl.h" /* NOLINT */
#include <string.h>
#define DART_API_DL_DEFINITIONS(name, R, A) name##_Type name##_DL = NULL;
DART_API_ALL_DL_SYMBOLS(DART_API_DL_DEFINITIONS)
#undef DART_API_DL_DEFINITIONS
typedef void* DartApiEntry_function;
DartApiEntry_function FindFunctionPointer(const DartApiEntry* entries,
const char* name) {
while (entries->name != NULL) {
if (strcmp(entries->name, name) == 0) return entries->function;
entries++;
}
return NULL;
}
intptr_t Dart_InitializeApiDL(void* data) {
DartApi* dart_api_data = (DartApi*)data;
if (dart_api_data->major != DART_API_DL_MAJOR_VERSION) {
// If the DartVM we're running on does not have the same version as this
// file was compiled against, refuse to initialize. The symbols are not
// compatible.
return -1;
}
// Minor versions are allowed to be different.
// If the DartVM has a higher minor version, it will provide more symbols
// than we initialize here.
// If the DartVM has a lower minor version, it will not provide all symbols.
// In that case, we leave the missing symbols un-initialized. Those symbols
// should not be used by the Dart and native code. The client is responsible
// for checking the minor version number himself based on which symbols it
// is using.
// (If we would error out on this case, recompiling native code against a
// newer SDK would break all uses on older SDKs, which is too strict.)
const DartApiEntry* dart_api_function_pointers = dart_api_data->functions;
#define DART_API_DL_INIT(name, R, A) \
name##_DL = \
(name##_Type)(FindFunctionPointer(dart_api_function_pointers, #name));
DART_API_ALL_DL_SYMBOLS(DART_API_DL_INIT)
#undef DART_API_DL_INIT
return 0;
}

View File

@@ -0,0 +1,156 @@
/*
* Copyright (c) 2020, 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.
*/
#ifndef RUNTIME_INCLUDE_DART_API_DL_H_
#define RUNTIME_INCLUDE_DART_API_DL_H_
#include "dart_api.h" /* NOLINT */
#include "dart_native_api.h" /* NOLINT */
/** \mainpage Dynamically Linked Dart API
*
* This exposes a subset of symbols from dart_api.h and dart_native_api.h
* available in every Dart embedder through dynamic linking.
*
* All symbols are postfixed with _DL to indicate that they are dynamically
* linked and to prevent conflicts with the original symbol.
*
* Link `dart_api_dl.c` file into your library and invoke
* `Dart_InitializeApiDL` with `NativeApi.initializeApiDLData`.
*/
DART_EXPORT intptr_t Dart_InitializeApiDL(void* data);
// ============================================================================
// IMPORTANT! Never update these signatures without properly updating
// DART_API_DL_MAJOR_VERSION and DART_API_DL_MINOR_VERSION.
//
// Verbatim copy of `dart_native_api.h` and `dart_api.h` symbol names and types
// to trigger compile-time errors if the symbols in those files are updated
// without updating these.
//
// Function return and argument types, and typedefs are carbon copied. Structs
// are typechecked nominally in C/C++, so they are not copied, instead a
// comment is added to their definition.
typedef int64_t Dart_Port_DL;
typedef void (*Dart_NativeMessageHandler_DL)(Dart_Port_DL dest_port_id,
Dart_CObject* message);
// dart_native_api.h symbols can be called on any thread.
#define DART_NATIVE_API_DL_SYMBOLS(F) \
/***** dart_native_api.h *****/ \
/* Dart_Port */ \
F(Dart_PostCObject, bool, (Dart_Port_DL port_id, Dart_CObject * message)) \
F(Dart_PostInteger, bool, (Dart_Port_DL port_id, int64_t message)) \
F(Dart_NewNativePort, Dart_Port_DL, \
(const char* name, Dart_NativeMessageHandler_DL handler, \
bool handle_concurrently)) \
F(Dart_CloseNativePort, bool, (Dart_Port_DL native_port_id))
// dart_api.h symbols can only be called on Dart threads.
#define DART_API_DL_SYMBOLS(F) \
/***** dart_api.h *****/ \
/* Errors */ \
F(Dart_IsError, bool, (Dart_Handle handle)) \
F(Dart_IsApiError, bool, (Dart_Handle handle)) \
F(Dart_IsUnhandledExceptionError, bool, (Dart_Handle handle)) \
F(Dart_IsCompilationError, bool, (Dart_Handle handle)) \
F(Dart_IsFatalError, bool, (Dart_Handle handle)) \
F(Dart_GetError, const char*, (Dart_Handle handle)) \
F(Dart_ErrorHasException, bool, (Dart_Handle handle)) \
F(Dart_ErrorGetException, Dart_Handle, (Dart_Handle handle)) \
F(Dart_ErrorGetStackTrace, Dart_Handle, (Dart_Handle handle)) \
F(Dart_NewApiError, Dart_Handle, (const char* error)) \
F(Dart_NewCompilationError, Dart_Handle, (const char* error)) \
F(Dart_NewUnhandledExceptionError, Dart_Handle, (Dart_Handle exception)) \
F(Dart_PropagateError, void, (Dart_Handle handle)) \
/* Dart_Handle, Dart_PersistentHandle, Dart_WeakPersistentHandle */ \
F(Dart_HandleFromPersistent, Dart_Handle, (Dart_PersistentHandle object)) \
F(Dart_HandleFromWeakPersistent, Dart_Handle, \
(Dart_WeakPersistentHandle object)) \
F(Dart_NewPersistentHandle, Dart_PersistentHandle, (Dart_Handle object)) \
F(Dart_SetPersistentHandle, void, \
(Dart_PersistentHandle obj1, Dart_Handle obj2)) \
F(Dart_DeletePersistentHandle, void, (Dart_PersistentHandle object)) \
F(Dart_NewWeakPersistentHandle, Dart_WeakPersistentHandle, \
(Dart_Handle object, void* peer, intptr_t external_allocation_size, \
Dart_HandleFinalizer callback)) \
F(Dart_DeleteWeakPersistentHandle, void, (Dart_WeakPersistentHandle object)) \
F(Dart_UpdateExternalSize, void, \
(Dart_WeakPersistentHandle object, intptr_t external_allocation_size)) \
F(Dart_NewFinalizableHandle, Dart_FinalizableHandle, \
(Dart_Handle object, void* peer, intptr_t external_allocation_size, \
Dart_HandleFinalizer callback)) \
F(Dart_DeleteFinalizableHandle, void, \
(Dart_FinalizableHandle object, Dart_Handle strong_ref_to_object)) \
F(Dart_UpdateFinalizableExternalSize, void, \
(Dart_FinalizableHandle object, Dart_Handle strong_ref_to_object, \
intptr_t external_allocation_size)) \
/* Isolates */ \
F(Dart_CurrentIsolate, Dart_Isolate, (void)) \
F(Dart_ExitIsolate, void, (void)) \
F(Dart_EnterIsolate, void, (Dart_Isolate)) \
/* Dart_Port */ \
F(Dart_Post, bool, (Dart_Port_DL port_id, Dart_Handle object)) \
F(Dart_NewSendPort, Dart_Handle, (Dart_Port_DL port_id)) \
F(Dart_SendPortGetId, Dart_Handle, \
(Dart_Handle port, Dart_Port_DL * port_id)) \
/* Scopes */ \
F(Dart_EnterScope, void, (void)) \
F(Dart_ExitScope, void, (void)) \
/* Objects */ \
F(Dart_IsNull, bool, (Dart_Handle))
#define DART_API_ALL_DL_SYMBOLS(F) \
DART_NATIVE_API_DL_SYMBOLS(F) \
DART_API_DL_SYMBOLS(F)
// IMPORTANT! Never update these signatures without properly updating
// DART_API_DL_MAJOR_VERSION and DART_API_DL_MINOR_VERSION.
//
// End of verbatim copy.
// ============================================================================
// Copy of definition of DART_EXPORT without 'used' attribute.
//
// The 'used' attribute cannot be used with DART_API_ALL_DL_SYMBOLS because
// they are not function declarations, but variable declarations with a
// function pointer type.
//
// The function pointer variables are initialized with the addresses of the
// functions in the VM. If we were to use function declarations instead, we
// would need to forward the call to the VM adding indirection.
#if defined(__CYGWIN__)
#error Tool chain and platform not supported.
#elif defined(_WIN32)
#if defined(DART_SHARED_LIB)
#define DART_EXPORT_DL DART_EXTERN_C __declspec(dllexport)
#else
#define DART_EXPORT_DL DART_EXTERN_C
#endif
#else
#if __GNUC__ >= 4
#if defined(DART_SHARED_LIB)
#define DART_EXPORT_DL DART_EXTERN_C __attribute__((visibility("default")))
#else
#define DART_EXPORT_DL DART_EXTERN_C
#endif
#else
#error Tool chain not supported.
#endif
#endif
#define DART_API_DL_DECLARATIONS(name, R, A) \
typedef R(*name##_Type) A; \
DART_EXPORT_DL name##_Type name##_DL;
DART_API_ALL_DL_SYMBOLS(DART_API_DL_DECLARATIONS)
#undef DART_API_DL_DECLARATIONS
#undef DART_EXPORT_DL
#endif /* RUNTIME_INCLUDE_DART_API_DL_H_ */ /* NOLINT */

View File

@@ -0,0 +1,108 @@
// Copyright (c) 2018, 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.
#ifndef RUNTIME_INCLUDE_DART_EMBEDDER_API_H_
#define RUNTIME_INCLUDE_DART_EMBEDDER_API_H_
#include "include/dart_api.h"
#include "include/dart_tools_api.h"
namespace dart {
namespace embedder {
// Initialize all subsystems of the embedder.
//
// Must be called before the `Dart_Initialize()` call to initialize the
// Dart VM.
//
// Returns true on success and false otherwise, in which case error would
// contain error message.
DART_WARN_UNUSED_RESULT bool InitOnce(char** error);
// Cleans up all subsystems of the embedder.
//
// Must be called after the `Dart_Cleanup()` call to initialize the
// Dart VM.
void Cleanup();
// Common arguments that are passed to isolate creation callback and to
// API methods that create isolates.
struct IsolateCreationData {
// URI for the main script that will be running in the isolate.
const char* script_uri;
// Advisory name of the main method that will be run by isolate.
// Only used for error messages.
const char* main;
// Isolate creation flags. Might be absent.
Dart_IsolateFlags* flags;
// Isolate group callback data.
void* isolate_group_data;
// Isolate callback data.
void* isolate_data;
};
// Create and initialize kernel-service isolate. This method should be used
// when VM invokes isolate creation callback with DART_KERNEL_ISOLATE_NAME as
// script_uri.
// The isolate is created from the given snapshot (might be kernel data or
// app-jit snapshot).
DART_WARN_UNUSED_RESULT Dart_Isolate
CreateKernelServiceIsolate(const IsolateCreationData& data,
const uint8_t* buffer,
intptr_t buffer_size,
char** error);
// Service isolate configuration.
struct VmServiceConfiguration {
enum {
kBindHttpServerToAFreePort = 0,
kDoNotAutoStartHttpServer = -1
};
// Address to which HTTP server will be bound.
const char* ip;
// Default port. See enum above for special values.
int port;
// If non-null, connection information for the VM service will be output to a
// file in JSON format at the location specified.
const char* write_service_info_filename;
// TODO(vegorov) document these ones.
bool dev_mode;
bool deterministic;
bool disable_auth_codes;
};
// Create and initialize vm-service isolate from the given AOT snapshot, which
// is expected to contain all necessary 'vm-service' libraries.
// This method should be used when VM invokes isolate creation callback with
// DART_VM_SERVICE_ISOLATE_NAME as script_uri.
DART_WARN_UNUSED_RESULT Dart_Isolate
CreateVmServiceIsolate(const IsolateCreationData& data,
const VmServiceConfiguration& config,
const uint8_t* isolate_data,
const uint8_t* isolate_instr,
char** error);
// Create and initialize vm-service isolate from the given kernel binary, which
// is expected to contain all necessary 'vm-service' libraries.
// This method should be used when VM invokes isolate creation callback with
// DART_VM_SERVICE_ISOLATE_NAME as script_uri.
DART_WARN_UNUSED_RESULT Dart_Isolate
CreateVmServiceIsolateFromKernel(const IsolateCreationData& data,
const VmServiceConfiguration& config,
const uint8_t* kernel_buffer,
intptr_t kernel_buffer_size,
char** error);
} // namespace embedder
} // namespace dart
#endif // RUNTIME_INCLUDE_DART_EMBEDDER_API_H_

View File

@@ -0,0 +1,207 @@
/*
* 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.
*/
#ifndef RUNTIME_INCLUDE_DART_NATIVE_API_H_
#define RUNTIME_INCLUDE_DART_NATIVE_API_H_
#include "dart_api.h" /* NOLINT */
/*
* ==========================================
* Message sending/receiving from native code
* ==========================================
*/
/**
* A Dart_CObject is used for representing Dart objects as native C
* data outside the Dart heap. These objects are totally detached from
* the Dart heap. Only a subset of the Dart objects have a
* representation as a Dart_CObject.
*
* The string encoding in the 'value.as_string' is UTF-8.
*
* All the different types from dart:typed_data are exposed as type
* kTypedData. The specific type from dart:typed_data is in the type
* field of the as_typed_data structure. The length in the
* as_typed_data structure is always in bytes.
*
* The data for kTypedData is copied on message send and ownership remains with
* the caller. The ownership of data for kExternalTyped is passed to the VM on
* message send and returned when the VM invokes the
* Dart_HandleFinalizer callback; a non-NULL callback must be provided.
*
* Note that Dart_CObject_kNativePointer is intended for internal use by
* dart:io implementation and has no connection to dart:ffi Pointer class.
* It represents a pointer to a native resource of a known type.
* The receiving side will only see this pointer as an integer and will not
* see the specified finalizer.
* The specified finalizer will only be invoked if the message is not delivered.
*/
typedef enum {
Dart_CObject_kNull = 0,
Dart_CObject_kBool,
Dart_CObject_kInt32,
Dart_CObject_kInt64,
Dart_CObject_kDouble,
Dart_CObject_kString,
Dart_CObject_kArray,
Dart_CObject_kTypedData,
Dart_CObject_kExternalTypedData,
Dart_CObject_kSendPort,
Dart_CObject_kCapability,
Dart_CObject_kNativePointer,
Dart_CObject_kUnsupported,
Dart_CObject_kUnmodifiableExternalTypedData,
Dart_CObject_kNumberOfTypes
} Dart_CObject_Type;
// This enum is versioned by DART_API_DL_MAJOR_VERSION, only add at the end
// and bump the DART_API_DL_MINOR_VERSION.
typedef struct _Dart_CObject {
Dart_CObject_Type type;
union {
bool as_bool;
int32_t as_int32;
int64_t as_int64;
double as_double;
const char* as_string;
struct {
Dart_Port id;
Dart_Port origin_id;
} as_send_port;
struct {
int64_t id;
} as_capability;
struct {
intptr_t length;
struct _Dart_CObject** values;
} as_array;
struct {
Dart_TypedData_Type type;
intptr_t length; /* in elements, not bytes */
const uint8_t* values;
} as_typed_data;
struct {
Dart_TypedData_Type type;
intptr_t length; /* in elements, not bytes */
uint8_t* data;
void* peer;
Dart_HandleFinalizer callback;
} as_external_typed_data;
struct {
intptr_t ptr;
intptr_t size;
Dart_HandleFinalizer callback;
} as_native_pointer;
} value;
} Dart_CObject;
// This struct is versioned by DART_API_DL_MAJOR_VERSION, bump the version when
// changing this struct.
/**
* Posts a message on some port. The message will contain the Dart_CObject
* object graph rooted in 'message'.
*
* While the message is being sent the state of the graph of Dart_CObject
* structures rooted in 'message' should not be accessed, as the message
* generation will make temporary modifications to the data. When the message
* has been sent the graph will be fully restored.
*
* If true is returned, the message was enqueued, and finalizers for external
* typed data will eventually run, even if the receiving isolate shuts down
* before processing the message. If false is returned, the message was not
* enqueued and ownership of external typed data in the message remains with the
* caller.
*
* This function may be called on any thread when the VM is running (that is,
* after Dart_Initialize has returned and before Dart_Cleanup has been called).
*
* \param port_id The destination port.
* \param message The message to send.
*
* \return True if the message was posted.
*/
DART_EXPORT bool Dart_PostCObject(Dart_Port port_id, Dart_CObject* message);
/**
* Posts a message on some port. The message will contain the integer 'message'.
*
* \param port_id The destination port.
* \param message The message to send.
*
* \return True if the message was posted.
*/
DART_EXPORT bool Dart_PostInteger(Dart_Port port_id, int64_t message);
/**
* A native message handler.
*
* This handler is associated with a native port by calling
* Dart_NewNativePort.
*
* The message received is decoded into the message structure. The
* lifetime of the message data is controlled by the caller. All the
* data references from the message are allocated by the caller and
* will be reclaimed when returning to it.
*/
typedef void (*Dart_NativeMessageHandler)(Dart_Port dest_port_id,
Dart_CObject* message);
/**
* Creates a new native port. When messages are received on this
* native port, then they will be dispatched to the provided native
* message handler.
*
* \param name The name of this port in debugging messages.
* \param handler The C handler to run when messages arrive on the port.
* \param handle_concurrently Is it okay to process requests on this
* native port concurrently?
*
* \return If successful, returns the port id for the native port. In
* case of error, returns ILLEGAL_PORT.
*/
DART_EXPORT Dart_Port Dart_NewNativePort(const char* name,
Dart_NativeMessageHandler handler,
bool handle_concurrently);
/* TODO(turnidge): Currently handle_concurrently is ignored. */
/**
* Closes the native port with the given id.
*
* The port must have been allocated by a call to Dart_NewNativePort.
*
* \param native_port_id The id of the native port to close.
*
* \return Returns true if the port was closed successfully.
*/
DART_EXPORT bool Dart_CloseNativePort(Dart_Port native_port_id);
/*
* ==================
* Verification Tools
* ==================
*/
/**
* Forces all loaded classes and functions to be compiled eagerly in
* the current isolate..
*
* TODO(turnidge): Document.
*/
DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_CompileAll(void);
/**
* Finalizes all classes.
*/
DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_FinalizeAllClasses(void);
/* This function is intentionally undocumented.
*
* It should not be used outside internal tests.
*/
DART_EXPORT void* Dart_ExecuteInternalCommand(const char* command, void* arg);
#endif /* INCLUDE_DART_NATIVE_API_H_ */ /* NOLINT */

View File

@@ -0,0 +1,588 @@
// Copyright (c) 2011, 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.
#ifndef RUNTIME_INCLUDE_DART_TOOLS_API_H_
#define RUNTIME_INCLUDE_DART_TOOLS_API_H_
#include "dart_api.h" /* NOLINT */
/** \mainpage Dart Tools Embedding API Reference
*
* This reference describes the Dart embedding API for tools. Tools include
* a debugger, service protocol, and timeline.
*
* NOTE: The APIs described in this file are unstable and subject to change.
*
* This reference is generated from the header include/dart_tools_api.h.
*/
/*
* ========
* Debugger
* ========
*/
/**
* ILLEGAL_ISOLATE_ID is a number guaranteed never to be associated with a
* valid isolate.
*/
#define ILLEGAL_ISOLATE_ID ILLEGAL_PORT
/**
* ILLEGAL_ISOLATE_GROUP_ID is a number guaranteed never to be associated with a
* valid isolate group.
*/
#define ILLEGAL_ISOLATE_GROUP_ID 0
/*
* =======
* Service
* =======
*/
/**
* A service request callback function.
*
* These callbacks, registered by the embedder, are called when the VM receives
* a service request it can't handle and the service request command name
* matches one of the embedder registered handlers.
*
* The return value of the callback indicates whether the response
* should be used as a regular result or an error result.
* Specifically, if the callback returns true, a regular JSON-RPC
* response is built in the following way:
*
* {
* "jsonrpc": "2.0",
* "result": <json_object>,
* "id": <some sequence id>,
* }
*
* If the callback returns false, a JSON-RPC error is built like this:
*
* {
* "jsonrpc": "2.0",
* "error": <json_object>,
* "id": <some sequence id>,
* }
*
* \param method The rpc method name.
* \param param_keys Service requests can have key-value pair parameters. The
* keys and values are flattened and stored in arrays.
* \param param_values The values associated with the keys.
* \param num_params The length of the param_keys and param_values arrays.
* \param user_data The user_data pointer registered with this handler.
* \param result A C string containing a valid JSON object. The returned
* pointer will be freed by the VM by calling free.
*
* \return True if the result is a regular JSON-RPC response, false if the
* result is a JSON-RPC error.
*/
typedef bool (*Dart_ServiceRequestCallback)(const char* method,
const char** param_keys,
const char** param_values,
intptr_t num_params,
void* user_data,
const char** json_object);
/**
* Register a Dart_ServiceRequestCallback to be called to handle
* requests for the named rpc on a specific isolate. The callback will
* be invoked with the current isolate set to the request target.
*
* \param method The name of the method that this callback is responsible for.
* \param callback The callback to invoke.
* \param user_data The user data passed to the callback.
*
* NOTE: If multiple callbacks with the same name are registered, only
* the last callback registered will be remembered.
*/
DART_EXPORT void Dart_RegisterIsolateServiceRequestCallback(
const char* method,
Dart_ServiceRequestCallback callback,
void* user_data);
/**
* Register a Dart_ServiceRequestCallback to be called to handle
* requests for the named rpc. The callback will be invoked without a
* current isolate.
*
* \param method The name of the command that this callback is responsible for.
* \param callback The callback to invoke.
* \param user_data The user data passed to the callback.
*
* NOTE: If multiple callbacks with the same name are registered, only
* the last callback registered will be remembered.
*/
DART_EXPORT void Dart_RegisterRootServiceRequestCallback(
const char* method,
Dart_ServiceRequestCallback callback,
void* user_data);
/**
* Embedder information which can be requested by the VM for internal or
* reporting purposes.
*
* The pointers in this structure are not going to be cached or freed by the VM.
*/
#define DART_EMBEDDER_INFORMATION_CURRENT_VERSION (0x00000001)
typedef struct {
int32_t version;
const char* name; // [optional] The name of the embedder
int64_t current_rss; // [optional] the current RSS of the embedder
int64_t max_rss; // [optional] the maximum RSS of the embedder
} Dart_EmbedderInformation;
/**
* Callback provided by the embedder that is used by the VM to request
* information.
*
* \return Returns a pointer to a Dart_EmbedderInformation structure.
* The embedder keeps the ownership of the structure and any field in it.
* The embedder must ensure that the structure will remain valid until the
* next invocation of the callback.
*/
typedef void (*Dart_EmbedderInformationCallback)(
Dart_EmbedderInformation* info);
/**
* Register a Dart_ServiceRequestCallback to be called to handle
* requests for the named rpc. The callback will be invoked without a
* current isolate.
*
* \param method The name of the command that this callback is responsible for.
* \param callback The callback to invoke.
* \param user_data The user data passed to the callback.
*
* NOTE: If multiple callbacks are registered, only the last callback registered
* will be remembered.
*/
DART_EXPORT void Dart_SetEmbedderInformationCallback(
Dart_EmbedderInformationCallback callback);
/**
* Invoke a vm-service method and wait for its result.
*
* \param request_json The utf8-encoded json-rpc request.
* \param request_json_length The length of the json-rpc request.
*
* \param response_json The returned utf8-encoded json response, must be
* free()ed by caller.
* \param response_json_length The length of the returned json response.
* \param error An optional error, must be free()ed by caller.
*
* \return Whether the call was successfully performed.
*
* NOTE: This method does not need a current isolate and must not have the
* vm-isolate being the current isolate. It must be called after
* Dart_Initialize() and before Dart_Cleanup().
*/
DART_EXPORT bool Dart_InvokeVMServiceMethod(uint8_t* request_json,
intptr_t request_json_length,
uint8_t** response_json,
intptr_t* response_json_length,
char** error);
/*
* ========
* Event Streams
* ========
*/
/**
* A callback invoked when the VM service gets a request to listen to
* some stream.
*
* \return Returns true iff the embedder supports the named stream id.
*/
typedef bool (*Dart_ServiceStreamListenCallback)(const char* stream_id);
/**
* A callback invoked when the VM service gets a request to cancel
* some stream.
*/
typedef void (*Dart_ServiceStreamCancelCallback)(const char* stream_id);
/**
* Adds VM service stream callbacks.
*
* \param listen_callback A function pointer to a listen callback function.
* A listen callback function should not be already set when this function
* is called. A NULL value removes the existing listen callback function
* if any.
*
* \param cancel_callback A function pointer to a cancel callback function.
* A cancel callback function should not be already set when this function
* is called. A NULL value removes the existing cancel callback function
* if any.
*
* \return Success if the callbacks were added. Otherwise, returns an
* error handle.
*/
DART_EXPORT char* Dart_SetServiceStreamCallbacks(
Dart_ServiceStreamListenCallback listen_callback,
Dart_ServiceStreamCancelCallback cancel_callback);
/**
* Sends a data event to clients of the VM Service.
*
* A data event is used to pass an array of bytes to subscribed VM
* Service clients. For example, in the standalone embedder, this is
* function used to provide WriteEvents on the Stdout and Stderr
* streams.
*
* If the embedder passes in a stream id for which no client is
* subscribed, then the event is ignored.
*
* \param stream_id The id of the stream on which to post the event.
*
* \param event_kind A string identifying what kind of event this is.
* For example, 'WriteEvent'.
*
* \param bytes A pointer to an array of bytes.
*
* \param bytes_length The length of the byte array.
*
* \return NULL if the arguments are well formed. Otherwise, returns an
* error string. The caller is responsible for freeing the error message.
*/
DART_EXPORT char* Dart_ServiceSendDataEvent(const char* stream_id,
const char* event_kind,
const uint8_t* bytes,
intptr_t bytes_length);
/*
* ========
* Reload support
* ========
*
* These functions are used to implement reloading in the Dart VM.
* This is an experimental feature, so embedders should be prepared
* for these functions to change.
*/
/**
* A callback which determines whether the file at some url has been
* modified since some time. If the file cannot be found, true should
* be returned.
*/
typedef bool (*Dart_FileModifiedCallback)(const char* url, int64_t since);
DART_EXPORT char* Dart_SetFileModifiedCallback(
Dart_FileModifiedCallback file_modified_callback);
/**
* Returns true if isolate is currently reloading.
*/
DART_EXPORT bool Dart_IsReloading();
/*
* ========
* Timeline
* ========
*/
/**
* Enable tracking of specified timeline category. This is operational
* only when systrace timeline functionality is turned on.
*
* \param categories A comma separated list of categories that need to
* be enabled, the categories are
* "all" : All categories
* "API" - Execution of Dart C API functions
* "Compiler" - Execution of Dart JIT compiler
* "CompilerVerbose" - More detailed Execution of Dart JIT compiler
* "Dart" - Execution of Dart code
* "Debugger" - Execution of Dart debugger
* "Embedder" - Execution of Dart embedder code
* "GC" - Execution of Dart Garbage Collector
* "Isolate" - Dart Isolate lifecycle execution
* "VM" - Execution in Dart VM runtime code
* "" - None
*
* When "all" is specified all the categories are enabled.
* When a comma separated list of categories is specified, the categories
* that are specified will be enabled and the rest will be disabled.
* When "" is specified all the categories are disabled.
* The category names are case sensitive.
* eg: Dart_EnableTimelineCategory("all");
* Dart_EnableTimelineCategory("GC,API,Isolate");
* Dart_EnableTimelineCategory("GC,Debugger,Dart");
*
* \return True if the categories were successfully enabled, False otherwise.
*/
DART_EXPORT bool Dart_SetEnabledTimelineCategory(const char* categories);
/**
* Returns a timestamp in microseconds. This timestamp is suitable for
* passing into the timeline system, and uses the same monotonic clock
* as dart:developer's Timeline.now.
*
* \return A timestamp that can be passed to the timeline system.
*/
DART_EXPORT int64_t Dart_TimelineGetMicros();
/**
* Returns a raw timestamp in from the monotonic clock.
*
* \return A raw timestamp from the monotonic clock.
*/
DART_EXPORT int64_t Dart_TimelineGetTicks();
/**
* Returns the frequency of the monotonic clock.
*
* \return The frequency of the monotonic clock.
*/
DART_EXPORT int64_t Dart_TimelineGetTicksFrequency();
typedef enum {
Dart_Timeline_Event_Begin, // Phase = 'B'.
Dart_Timeline_Event_End, // Phase = 'E'.
Dart_Timeline_Event_Instant, // Phase = 'i'.
Dart_Timeline_Event_Duration, // Phase = 'X'.
Dart_Timeline_Event_Async_Begin, // Phase = 'b'.
Dart_Timeline_Event_Async_End, // Phase = 'e'.
Dart_Timeline_Event_Async_Instant, // Phase = 'n'.
Dart_Timeline_Event_Counter, // Phase = 'C'.
Dart_Timeline_Event_Flow_Begin, // Phase = 's'.
Dart_Timeline_Event_Flow_Step, // Phase = 't'.
Dart_Timeline_Event_Flow_End, // Phase = 'f'.
} Dart_Timeline_Event_Type;
/**
* Add a timeline event to the embedder stream.
*
* \param label The name of the event. Its lifetime must extend at least until
* Dart_Cleanup.
* \param timestamp0 The first timestamp of the event.
* \param timestamp1_or_async_id The second timestamp of the event or
* the async id.
* \param argument_count The number of argument names and values.
* \param argument_names An array of names of the arguments. The lifetime of the
* names must extend at least until Dart_Cleanup. The array may be reclaimed
* when this call returns.
* \param argument_values An array of values of the arguments. The values and
* the array may be reclaimed when this call returns.
*/
DART_EXPORT void Dart_TimelineEvent(const char* label,
int64_t timestamp0,
int64_t timestamp1_or_async_id,
Dart_Timeline_Event_Type type,
intptr_t argument_count,
const char** argument_names,
const char** argument_values);
/**
* Associates a name with the current thread. This name will be used to name
* threads in the timeline. Can only be called after a call to Dart_Initialize.
*
* \param name The name of the thread.
*/
DART_EXPORT void Dart_SetThreadName(const char* name);
typedef struct {
const char* name;
const char* value;
} Dart_TimelineRecorderEvent_Argument;
#define DART_TIMELINE_RECORDER_CURRENT_VERSION (0x00000002)
typedef struct {
/* Set to DART_TIMELINE_RECORDER_CURRENT_VERSION */
int32_t version;
/* The event's type / phase. */
Dart_Timeline_Event_Type type;
/* The event's timestamp according to the same clock as
* Dart_TimelineGetMicros. For a duration event, this is the beginning time.
*/
int64_t timestamp0;
/* For a duration event, this is the end time. For an async event, this is the
* async id. */
int64_t timestamp1_or_async_id;
/* The current isolate of the event, as if by Dart_GetMainPortId, or
* ILLEGAL_PORT if the event had no current isolate. */
Dart_Port isolate;
/* The current isolate group of the event, as if by
* Dart_CurrentIsolateGroupId, or ILLEGAL_PORT if the event had no current
* isolate group. */
Dart_IsolateGroupId isolate_group;
/* The callback data associated with the isolate if any. */
void* isolate_data;
/* The callback data associated with the isolate group if any. */
void* isolate_group_data;
/* The name / label of the event. */
const char* label;
/* The stream / category of the event. */
const char* stream;
intptr_t argument_count;
Dart_TimelineRecorderEvent_Argument* arguments;
} Dart_TimelineRecorderEvent;
/**
* Callback provided by the embedder to handle the completion of timeline
* events.
*
* \param event A timeline event that has just been completed. The VM keeps
* ownership of the event and any field in it (i.e., the embedder should copy
* any values it needs after the callback returns).
*/
typedef void (*Dart_TimelineRecorderCallback)(
Dart_TimelineRecorderEvent* event);
/**
* Register a `Dart_TimelineRecorderCallback` to be called as timeline events
* are completed.
*
* The callback will be invoked without a current isolate.
*
* The callback will be invoked on the thread completing the event. Because
* `Dart_TimelineEvent` may be called by any thread, the callback may be called
* on any thread.
*
* The callback may be invoked at any time after `Dart_Initialize` is called and
* before `Dart_Cleanup` returns.
*
* If multiple callbacks are registered, only the last callback registered
* will be remembered. Providing a NULL callback will clear the registration
* (i.e., a NULL callback produced a no-op instead of a crash).
*
* Setting a callback is insufficient to receive events through the callback. The
* VM flag `timeline_recorder` must also be set to `callback`.
*/
DART_EXPORT void Dart_SetTimelineRecorderCallback(
Dart_TimelineRecorderCallback callback);
/*
* =======
* Metrics
* =======
*/
/**
* Return metrics gathered for the VM and individual isolates.
*/
DART_EXPORT int64_t
Dart_IsolateGroupHeapOldUsedMetric(Dart_IsolateGroup group); // Byte
DART_EXPORT int64_t
Dart_IsolateGroupHeapOldCapacityMetric(Dart_IsolateGroup group); // Byte
DART_EXPORT int64_t
Dart_IsolateGroupHeapOldExternalMetric(Dart_IsolateGroup group); // Byte
DART_EXPORT int64_t
Dart_IsolateGroupHeapNewUsedMetric(Dart_IsolateGroup group); // Byte
DART_EXPORT int64_t
Dart_IsolateGroupHeapNewCapacityMetric(Dart_IsolateGroup group); // Byte
DART_EXPORT int64_t
Dart_IsolateGroupHeapNewExternalMetric(Dart_IsolateGroup group); // Byte
/*
* ========
* UserTags
* ========
*/
/*
* Gets the current isolate's currently set UserTag instance.
*
* \return The currently set UserTag instance.
*/
DART_EXPORT Dart_Handle Dart_GetCurrentUserTag();
/*
* Gets the current isolate's default UserTag instance.
*
* \return The default UserTag with label 'Default'
*/
DART_EXPORT Dart_Handle Dart_GetDefaultUserTag();
/*
* Creates a new UserTag instance.
*
* \param label The name of the new UserTag.
*
* \return The newly created UserTag instance or an error handle.
*/
DART_EXPORT Dart_Handle Dart_NewUserTag(const char* label);
/*
* Updates the current isolate's UserTag to a new value.
*
* \param user_tag The UserTag to be set as the current UserTag.
*
* \return The previously set UserTag instance or an error handle.
*/
DART_EXPORT Dart_Handle Dart_SetCurrentUserTag(Dart_Handle user_tag);
/*
* Returns the label of a given UserTag instance.
*
* \param user_tag The UserTag from which the label will be retrieved.
*
* \return The UserTag's label. NULL if the user_tag is invalid. The caller is
* responsible for freeing the returned label.
*/
DART_EXPORT DART_WARN_UNUSED_RESULT char* Dart_GetUserTagLabel(
Dart_Handle user_tag);
/*
* =======
* Heap Snapshot
* =======
*/
/**
* Callback provided by the caller of `Dart_WriteHeapSnapshot` which is
* used to write out chunks of the requested heap snapshot.
*
* \param context An opaque context which was passed to `Dart_WriteHeapSnapshot`
* together with this callback.
*
* \param buffer Pointer to the buffer containing a chunk of the snapshot.
* The callback owns the buffer and needs to `free` it.
*
* \param size Number of bytes in the `buffer` to be written.
*
* \param is_last Set to `true` for the last chunk. The callback will not
* be invoked again after it was invoked once with `is_last` set to `true`.
*/
typedef void (*Dart_HeapSnapshotWriteChunkCallback)(void* context,
uint8_t* buffer,
intptr_t size,
bool is_last);
/**
* Generate heap snapshot of the current isolate group and stream it into the
* given `callback`. VM would produce snapshot in chunks and send these chunks
* one by one back to the embedder by invoking the provided `callback`.
*
* This API enables embedder to stream snapshot into a file or socket without
* allocating a buffer to hold the whole snapshot in memory.
*
* The isolate group will be paused for the duration of this operation.
*
* \param write Callback used to write chunks of the heap snapshot.
*
* \param context Opaque context which would be passed on each invocation of
* `write` callback.
*
* \returns `nullptr` if the operation is successful otherwise error message.
* Caller owns error message string and needs to `free` it.
*/
DART_EXPORT char* Dart_WriteHeapSnapshot(
Dart_HeapSnapshotWriteChunkCallback write,
void* context);
#endif // RUNTIME_INCLUDE_DART_TOOLS_API_H_

View File

@@ -0,0 +1,16 @@
/*
* Copyright (c) 2020, 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.
*/
#ifndef RUNTIME_INCLUDE_DART_VERSION_H_
#define RUNTIME_INCLUDE_DART_VERSION_H_
// On breaking changes the major version is increased.
// On backwards compatible changes the minor version is increased.
// The versioning covers the symbols exposed in dart_api_dl.h
#define DART_API_DL_MAJOR_VERSION 2
#define DART_API_DL_MINOR_VERSION 3
#endif /* RUNTIME_INCLUDE_DART_VERSION_H_ */ /* NOLINT */

Some files were not shown because too many files have changed in this diff Show More