@@ -18,25 +18,21 @@ import android.util.Log
18
18
import com.beust.klaxon.Klaxon
19
19
import com.wireguard.android.backend.*
20
20
import com.wireguard.crypto.KeyPair
21
+ import io.flutter.plugin.common.EventChannel
21
22
import kotlinx.coroutines.*
22
23
23
24
24
25
import kotlinx.coroutines.launch
25
26
import java.io.ByteArrayInputStream
26
27
27
- /* * WireguardDartPlugin */
28
-
29
28
const val PERMISSIONS_REQUEST_CODE = 10014
30
- const val METHOD_CHANNEL_NAME = " wireguard_dart"
31
29
32
30
class WireguardDartPlugin : FlutterPlugin , MethodCallHandler , ActivityAware ,
33
- PluginRegistry .ActivityResultListener {
34
- // / The MethodChannel that will the communication between Flutter and native Android
35
- // /
36
- // / This local reference serves to register the plugin with the Flutter Engine and unregister it
37
- // / when the Flutter Engine is detached from the Activity
31
+ PluginRegistry .ActivityResultListener {
32
+
38
33
private lateinit var channel: MethodChannel
39
- private lateinit var tunnelName: String
34
+ private lateinit var statusChannel: EventChannel
35
+ private lateinit var statusBroadcaster: ConnectionStatusBroadcaster
40
36
private val futureBackend = CompletableDeferred <Backend >()
41
37
private val scope = CoroutineScope (Job () + Dispatchers .Main .immediate)
42
38
private var backend: Backend ? = null
@@ -45,15 +41,21 @@ class WireguardDartPlugin : FlutterPlugin, MethodCallHandler, ActivityAware,
45
41
private var activity: Activity ? = null
46
42
private var config: com.wireguard.config.Config ? = null
47
43
private var tunnel: WireguardTunnel ? = null
48
- private lateinit var status: ConnectionStatus
44
+ private var status: ConnectionStatus = ConnectionStatus .disconnected
45
+ set(value) {
46
+ field = value
47
+ if (::statusBroadcaster.isInitialized) {
48
+ statusBroadcaster.send(value)
49
+ }
50
+ }
49
51
50
52
companion object {
51
53
const val TAG = " MainActivity"
52
54
}
53
55
54
56
override fun onActivityResult (requestCode : Int , resultCode : Int , data : Intent ? ): Boolean {
55
57
havePermission =
56
- (requestCode == PERMISSIONS_REQUEST_CODE ) && (resultCode == Activity .RESULT_OK )
58
+ (requestCode == PERMISSIONS_REQUEST_CODE ) && (resultCode == Activity .RESULT_OK )
57
59
return havePermission
58
60
}
59
61
@@ -74,7 +76,10 @@ class WireguardDartPlugin : FlutterPlugin, MethodCallHandler, ActivityAware,
74
76
}
75
77
76
78
override fun onAttachedToEngine (flutterPluginBinding : FlutterPlugin .FlutterPluginBinding ) {
77
- channel = MethodChannel (flutterPluginBinding.binaryMessenger, METHOD_CHANNEL_NAME )
79
+ channel = MethodChannel (flutterPluginBinding.binaryMessenger, " wireguard_dart" )
80
+ statusChannel = EventChannel (flutterPluginBinding.binaryMessenger, " wireguard_dart.status" )
81
+ statusBroadcaster = ConnectionStatusBroadcaster ()
82
+ statusChannel.setStreamHandler(statusBroadcaster)
78
83
context = flutterPluginBinding.applicationContext
79
84
80
85
scope.launch(Dispatchers .IO ) {
@@ -128,10 +133,10 @@ class WireguardDartPlugin : FlutterPlugin, MethodCallHandler, ActivityAware,
128
133
private fun generateKeyPair (result : Result ) {
129
134
val keyPair = KeyPair ()
130
135
result.success(
131
- hashMapOf(
132
- " privateKey" to keyPair.privateKey.toBase64(),
133
- " publicKey" to keyPair.publicKey.toBase64()
134
- )
136
+ hashMapOf(
137
+ " privateKey" to keyPair.privateKey.toBase64(),
138
+ " publicKey" to keyPair.publicKey.toBase64()
139
+ )
135
140
)
136
141
}
137
142
@@ -141,14 +146,11 @@ class WireguardDartPlugin : FlutterPlugin, MethodCallHandler, ActivityAware,
141
146
flutterError(result, " Invalid Name" )
142
147
return @launch
143
148
}
144
- tunnelName = bundleId
145
149
checkPermission()
146
- tunnel = WireguardTunnel (tunnelName)
147
- status = when (backend?.getState(tunnel!! )) {
148
- Tunnel .State .UP -> ConnectionStatus .connected
149
- Tunnel .State .DOWN -> ConnectionStatus .disconnected
150
- else -> ConnectionStatus .unknown
150
+ tunnel = WireguardTunnel (bundleId) { state ->
151
+ status = ConnectionStatus .fromTunnelState(state)
151
152
}
153
+ status = ConnectionStatus .fromTunnelState(backend?.getState(tunnel!! ))
152
154
result.success(null )
153
155
}
154
156
}
@@ -158,6 +160,7 @@ class WireguardDartPlugin : FlutterPlugin, MethodCallHandler, ActivityAware,
158
160
result.error(" err_setup_tunnel" , " Tunnel is not initialized" , null )
159
161
return
160
162
}
163
+ status = ConnectionStatus .connecting
161
164
scope.launch(Dispatchers .IO ) {
162
165
try {
163
166
if (! havePermission) {
@@ -168,11 +171,9 @@ class WireguardDartPlugin : FlutterPlugin, MethodCallHandler, ActivityAware,
168
171
config = com.wireguard.config.Config .parse(inputStream)
169
172
futureBackend.await().setState(tun, Tunnel .State .UP , config);
170
173
flutterSuccess(result, " " )
171
- } catch (e: BackendException ) {
172
- Log .e(TAG , " Connect - BackendException - ERROR - ${e.reason} " , e)
173
- flutterError(result, e.reason.toString())
174
174
} catch (e: Throwable ) {
175
175
Log .e(TAG , " Connect - Can't connect to tunnel: $e " , e)
176
+ status = queryStatus()
176
177
flutterError(result, e.message.toString())
177
178
}
178
179
}
@@ -190,11 +191,9 @@ class WireguardDartPlugin : FlutterPlugin, MethodCallHandler, ActivityAware,
190
191
}
191
192
futureBackend.await().setState(tun, Tunnel .State .DOWN , config)
192
193
flutterSuccess(result, " " )
193
- } catch (e: BackendException ) {
194
- Log .e(TAG , " Disconnect - BackendException - ERROR - ${e.reason} " , e)
195
- flutterError(result, e.reason.toString())
196
194
} catch (e: Throwable ) {
197
195
Log .e(TAG , " Disconnect - Can't disconnect from tunnel: ${e.message} " )
196
+ status = queryStatus()
198
197
flutterError(result, e.message.toString())
199
198
}
200
199
}
@@ -212,9 +211,9 @@ class WireguardDartPlugin : FlutterPlugin, MethodCallHandler, ActivityAware,
212
211
val stats = Stats (statistics.totalRx(), statistics.totalTx())
213
212
214
213
flutterSuccess(
215
- result, Klaxon ().toJsonString(
214
+ result, Klaxon ().toJsonString(
216
215
stats
217
- )
216
+ )
218
217
)
219
218
Log .i(TAG , " Statistics - ${stats.totalDownload} ${stats.totalUpload} " )
220
219
@@ -243,23 +242,26 @@ class WireguardDartPlugin : FlutterPlugin, MethodCallHandler, ActivityAware,
243
242
}
244
243
245
244
private fun status (result : Result ) {
245
+ val status = queryStatus()
246
+ result.success(hashMapOf(" status" to status.name))
247
+ }
248
+
249
+ private fun queryStatus (): ConnectionStatus {
246
250
if (tunnel == null ) {
247
- flutterError(result, " Tunnel has not been initialized" )
248
- return
251
+ return ConnectionStatus .unknown
249
252
}
250
- val status = when (backend?.getState(tunnel!! )) {
253
+ return when (backend?.getState(tunnel!! )) {
251
254
Tunnel .State .DOWN -> ConnectionStatus .disconnected
252
255
Tunnel .State .UP -> ConnectionStatus .connected
253
256
else -> ConnectionStatus .unknown
254
257
}
255
- result.success(hashMapOf(" status" to status.name))
256
258
}
257
259
}
258
260
259
261
typealias StateChangeCallback = (Tunnel .State ) -> Unit
260
262
261
263
class WireguardTunnel (
262
- private val name : String , private val onStateChanged : StateChangeCallback ? = null
264
+ private val name : String , private val onStateChanged : StateChangeCallback ? = null
263
265
) : Tunnel {
264
266
265
267
override fun getName () = name
@@ -271,8 +273,8 @@ class WireguardTunnel(
271
273
}
272
274
273
275
class Stats (
274
- val totalDownload : Long ,
275
- val totalUpload : Long ,
276
+ val totalDownload : Long ,
277
+ val totalUpload : Long ,
276
278
)
277
279
278
280
0 commit comments