114 lines
4.3 KiB
Kotlin
114 lines
4.3 KiB
Kotlin
|
|
package com.novoyuuparosk.iperf3gui
|
||
|
|
|
||
|
|
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
||
|
|
import io.flutter.plugin.common.MethodChannel
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Kotlin binding layer for native iperf3 via JNI.
|
||
|
|
*
|
||
|
|
* This class loads the native library (libiperf3jni.so) and exposes
|
||
|
|
* iperf3 functionality to Flutter via MethodChannel callbacks.
|
||
|
|
*
|
||
|
|
* iperf3 runs natively inside the app process — no Process.start() needed,
|
||
|
|
* no SELinux restrictions. Output is streamed live to the Flutter UI via
|
||
|
|
* the IperfCallback interface.
|
||
|
|
*/
|
||
|
|
object IperfRunner : FlutterPlugin {
|
||
|
|
|
||
|
|
private var channel: MethodChannel? = null
|
||
|
|
|
||
|
|
init {
|
||
|
|
// Load native library at class initialization
|
||
|
|
System.loadLibrary("iperf3jni")
|
||
|
|
}
|
||
|
|
|
||
|
|
override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
|
||
|
|
channel = MethodChannel(binding.binaryMessenger, "com.novoyuuparosk.iperf3gui/iperf")
|
||
|
|
channel?.setMethodCallHandler { call, result ->
|
||
|
|
when (call.method) {
|
||
|
|
"runIperf" -> {
|
||
|
|
val args = call.argument<Array<String>>("args")
|
||
|
|
if (args != null) {
|
||
|
|
runIperfLive(args, object : IperfCallback {
|
||
|
|
override fun onOutput(line: String) {
|
||
|
|
channel?.invokeMethod("onOutput", mapOf("output" to line))
|
||
|
|
}
|
||
|
|
override fun onError(error: String) {
|
||
|
|
channel?.invokeMethod("onError", mapOf("error" to error))
|
||
|
|
}
|
||
|
|
override fun onComplete() {
|
||
|
|
channel?.invokeMethod("onComplete", emptyMap<String, Any>())
|
||
|
|
}
|
||
|
|
})
|
||
|
|
result.success(null)
|
||
|
|
} else {
|
||
|
|
result.error("INVALID_ARGS", "args must be a String array", null)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
"stopIperf" -> {
|
||
|
|
forceStopIperfTest(object : IperfCallback {
|
||
|
|
override fun onOutput(line: String) {
|
||
|
|
channel?.invokeMethod("onOutput", mapOf("output" to line))
|
||
|
|
}
|
||
|
|
override fun onError(error: String) {
|
||
|
|
channel?.invokeMethod("onError", mapOf("error" to error))
|
||
|
|
}
|
||
|
|
override fun onComplete() {
|
||
|
|
channel?.invokeMethod("onComplete", emptyMap<String, Any>())
|
||
|
|
}
|
||
|
|
})
|
||
|
|
result.success(null)
|
||
|
|
}
|
||
|
|
"isTestRunning" -> {
|
||
|
|
result.success(isTestRunning())
|
||
|
|
}
|
||
|
|
else -> {
|
||
|
|
result.notImplemented()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
|
||
|
|
channel = null
|
||
|
|
}
|
||
|
|
|
||
|
|
// ─────────────────────────────────────────────────────────────────
|
||
|
|
// Native method bindings
|
||
|
|
// ─────────────────────────────────────────────────────────────────
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Start an iperf3 test with the given arguments.
|
||
|
|
* This calls the native C function via JNI.
|
||
|
|
*/
|
||
|
|
external fun runIperfLive(arguments: Array<String>, callback: IperfCallback)
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Gracefully stop a running iperf3 test.
|
||
|
|
*/
|
||
|
|
external fun forceStopIperfTest(callback: IperfCallback)
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Check if an iperf3 test is currently running.
|
||
|
|
* @return true if a test is in progress, false otherwise
|
||
|
|
*/
|
||
|
|
external fun isTestRunning(): Boolean
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Callback interface for iperf3 test output.
|
||
|
|
*
|
||
|
|
* Used by the native layer to stream test results back to Flutter
|
||
|
|
* in real-time.
|
||
|
|
*/
|
||
|
|
interface IperfCallback {
|
||
|
|
/** Called with each line of iperf3 output (stdout/stderr) */
|
||
|
|
fun onOutput(line: String)
|
||
|
|
|
||
|
|
/** Called when an error occurs */
|
||
|
|
fun onError(error: String)
|
||
|
|
|
||
|
|
/** Called when the test completes (success or failure) */
|
||
|
|
fun onComplete()
|
||
|
|
}
|
||
|
|
}
|