changed scope.cancel, 当协程上下文被取消,会将资源做对应处理
This commit is contained in:
parent
fa2453a733
commit
867fb5ca72
@ -24,6 +24,7 @@ import com.jihe.punchnet.sdlan.network.DeviceConfig
|
||||
import com.jihe.punchnet.sdlan.network.IfaceTun
|
||||
import com.jihe.punchnet.sdlan.network.RouteDetail
|
||||
import com.jihe.punchnet.sdlan.network.RouteTable
|
||||
import com.jihe.punchnet.sdlan.network.StartStopChanInfo
|
||||
import com.jihe.punchnet.sdlan.network.cidrToRouteDetail
|
||||
import com.jihe.punchnet.sdlan.network.ipInt2ByteArray
|
||||
import com.jihe.punchnet.sdlan.network.maskIPToDigit
|
||||
@ -33,6 +34,7 @@ import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.FileInputStream
|
||||
@ -50,6 +52,7 @@ class PunchnetService : VpnService() , IfaceTun {
|
||||
private val serviceLock = Any()
|
||||
private val isRunning = AtomicBoolean(false)
|
||||
|
||||
private val start_stop_channel = Channel<StartStopChanInfo>(100)
|
||||
|
||||
var input: FileInputStream? = null
|
||||
var output: FileOutputStream? = null
|
||||
@ -64,6 +67,10 @@ class PunchnetService : VpnService() , IfaceTun {
|
||||
const val ACTION_DISCONNECT = "com.jihe.punchnet.punchnetservice.DISCONNECT"
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
vpnDescriptor?.close()
|
||||
}
|
||||
|
||||
override suspend fun recv(): ByteArray {
|
||||
val result = withContext(Dispatchers.IO) {
|
||||
val result = ByteArray(1500)
|
||||
@ -135,18 +142,18 @@ class PunchnetService : VpnService() , IfaceTun {
|
||||
}
|
||||
|
||||
Toast.makeText(this, "stop vpn called", Toast.LENGTH_LONG).show()
|
||||
stopForeground(STOP_FOREGROUND_REMOVE)
|
||||
input?.close()
|
||||
output?.close()
|
||||
vpnDescriptor?.close()
|
||||
|
||||
vpnDescriptor = null
|
||||
|
||||
stopForeground(STOP_FOREGROUND_REMOVE)
|
||||
stopSelf()
|
||||
isRunning.set(false)
|
||||
}
|
||||
}
|
||||
|
||||
private fun connect(startArg: PunchnetServiceArgument?) {
|
||||
|
||||
synchronized(serviceLock) {
|
||||
if (isRunning.get()) {
|
||||
return
|
||||
@ -183,13 +190,13 @@ class PunchnetService : VpnService() , IfaceTun {
|
||||
name = "tau",
|
||||
)
|
||||
|
||||
scope.launch {
|
||||
run_sdlan(scope, iface, argument, startArg)
|
||||
}
|
||||
|
||||
val notification = createNotification()
|
||||
startForeground(1, notification)
|
||||
|
||||
scope.launch {
|
||||
run_sdlan(scope, start_stop_channel, iface, argument, startArg)
|
||||
}
|
||||
|
||||
isRunning.set(true)
|
||||
}
|
||||
}
|
||||
@ -199,12 +206,13 @@ class PunchnetService : VpnService() , IfaceTun {
|
||||
|
||||
return if (intent?.action == ACTION_DISCONNECT) {
|
||||
scope.cancel()
|
||||
disconnect()
|
||||
START_STICKY
|
||||
} else {
|
||||
|
||||
scope = CoroutineScope(Dispatchers.IO)
|
||||
arpTable = ARPTable(scope)
|
||||
|
||||
disconnect()
|
||||
START_NOT_STICKY
|
||||
} else {
|
||||
val argument = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
intent?.getParcelableExtra("argument", PunchnetServiceArgument::class.java)
|
||||
} else {
|
||||
@ -238,7 +246,9 @@ class PunchnetService : VpnService() , IfaceTun {
|
||||
// scope.cancel()
|
||||
// disconnect()
|
||||
scope.cancel()
|
||||
stopForeground(STOP_FOREGROUND_REMOVE)
|
||||
disconnect()
|
||||
Log.e(TAG, "onDestroy is called")
|
||||
// stopForeground(STOP_FOREGROUND_REMOVE)
|
||||
super.onDestroy()
|
||||
}
|
||||
}
|
||||
@ -7,6 +7,7 @@ import com.jihe.punchnet.protobuf.PunchProto.SDLStunProbe
|
||||
import com.jihe.punchnet.protobuf.PunchProto.SDLStunProbeReply
|
||||
import com.jihe.punchnet.protobuf.PunchProto.SDLStunRequest
|
||||
import com.jihe.punchnet.sdlan.config.SDLanMulticastConfig
|
||||
import com.jihe.punchnet.sdlan.logs.TerminalLogger
|
||||
import com.jihe.punchnet.sdlan.utils.AES
|
||||
import com.jihe.punchnet.sdlan.utils.RSA
|
||||
import com.jihe.punchnet.sdlan.utils.UniqueNodeID
|
||||
@ -312,8 +313,12 @@ class Node private constructor (
|
||||
}
|
||||
|
||||
suspend fun _sendDataToSocket(msg: ByteArray) {
|
||||
|
||||
if (aes.isAuthorized()) {
|
||||
TerminalLogger.debugf{"authorized, ping to sn"}
|
||||
toSocket.send(msg)
|
||||
} else {
|
||||
TerminalLogger.debugf{"unauthorized, not ping to sn"}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,6 +30,7 @@ interface Iface {
|
||||
suspend fun send(content: ByteArray)
|
||||
suspend fun reload_config(config: DeviceConfig)
|
||||
|
||||
fun close() {}
|
||||
suspend fun handleDataFromNet(node: Node, data: ByteArray)
|
||||
suspend fun handleDataFromDevice(node: Node, data: ByteArray)
|
||||
}
|
||||
@ -227,6 +228,9 @@ class IfaceMock: IfaceTun {
|
||||
|
||||
var config: DeviceConfig = DeviceConfig(0)
|
||||
|
||||
override fun close() {
|
||||
}
|
||||
|
||||
override suspend fun recv(): ByteArray {
|
||||
val result = withContext(Dispatchers.IO) {
|
||||
val size = input.readInt()
|
||||
|
||||
@ -26,6 +26,7 @@ import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.channels.ReceiveChannel
|
||||
import kotlinx.coroutines.channels.SendChannel
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.selects.select
|
||||
import kotlinx.coroutines.withContext
|
||||
@ -47,7 +48,6 @@ suspend fun onMessage(scope: CoroutineScope, data: SDLanTCP) {
|
||||
TerminalLogger.debugf {"message received"}
|
||||
when(data.packetType) {
|
||||
PacketType.RegisterSuperACK -> {
|
||||
println("11")
|
||||
val ack = SDLRegisterSuperAck.parseFrom(data.currentPacket)
|
||||
// TerminalLogger.debugf { "got register super ack: $ack" }
|
||||
println("ack is ${ack}")
|
||||
@ -65,7 +65,9 @@ suspend fun onMessage(scope: CoroutineScope, data: SDLanTCP) {
|
||||
node.deviceConfig.ip.netAddr = ack.devAddr.netAddr
|
||||
node.deviceConfig.ip.netBitLen = ack.devAddr.netBitLen.toByte()
|
||||
|
||||
println("reloading config: node.iface = ${node.iface}")
|
||||
node.iface?.reload_config(node.deviceConfig)
|
||||
println("reloading config ok: node.iface = ${node.iface}")
|
||||
|
||||
node.networkID.set(ack.devAddr.networkId)
|
||||
// println("got aes key: ${aeskey.toList()}, length is ${aeskey.size}")
|
||||
@ -83,7 +85,6 @@ suspend fun onMessage(scope: CoroutineScope, data: SDLanTCP) {
|
||||
*/
|
||||
}
|
||||
PacketType.RegisterSuperNAK -> {
|
||||
println("21")
|
||||
val nak = SDLRegisterSuperNak.parseFrom(data.currentPacket)
|
||||
TerminalLogger.debugf { "got register super nak: $nak" }
|
||||
val nakcode = NakMsgCode.fromByte(nak.errorCode.toByte())
|
||||
@ -133,7 +134,7 @@ suspend fun onMessage(scope: CoroutineScope, data: SDLanTCP) {
|
||||
|
||||
}
|
||||
|
||||
suspend fun run_sdlan(scope: CoroutineScope, iface: Iface, argument: Arguments, routeinfo: PunchnetServiceArgument?) {
|
||||
suspend fun run_sdlan(scope: CoroutineScope, start_stop_channel: Channel<StartStopChanInfo>, iface: Iface, argument: Arguments, routeinfo: PunchnetServiceArgument?) {
|
||||
UniqueNodeID.setBaseDir(argument.baseDir)
|
||||
val edgeUUID = UniqueNodeID.getUUID()
|
||||
val config = parseConfig(edgeUUID, argument)
|
||||
@ -146,7 +147,7 @@ suspend fun run_sdlan(scope: CoroutineScope, iface: Iface, argument: Arguments,
|
||||
|
||||
|
||||
val toSocket = Channel<ByteArray>(100)
|
||||
val start_stop_channel = Channel<StartStopChanInfo>(100)
|
||||
// val start_stop_channel = Channel<StartStopChanInfo>(100)
|
||||
initEdge(scope, iface, argument.token, config, toSocket, start_stop_channel)
|
||||
|
||||
val tcp = argument.tcp.split(":")
|
||||
@ -158,10 +159,10 @@ suspend fun run_sdlan(scope: CoroutineScope, iface: Iface, argument: Arguments,
|
||||
|
||||
val before = ubyteArrayOf(126u,162u,25u,63u,148u,147u,198u,41u,69u,165u,149u,101u,153u,82u,190u,21u,48u,120u,26u,64u,142u,103u,159u,60u,47u,129u,176u,17u,232u,210u,36u,56u)
|
||||
val encrypted = node.rsa.encrypt(before.toByteArray(), use_private_key = false)
|
||||
println("encrypted: ${encrypted.contentToString()}")
|
||||
// println("encrypted: ${encrypted.contentToString()}")
|
||||
val origin = node.rsa.decrypt(encrypted, use_pub_key = false)
|
||||
TerminalLogger.debugf { "got encrypted ${encrypted.size}"}
|
||||
TerminalLogger.debugf { "got origin ${origin.contentToString()}"}
|
||||
// TerminalLogger.debugf { "got encrypted ${encrypted.size}"}
|
||||
// TerminalLogger.debugf { "got origin ${origin.contentToString()}"}
|
||||
|
||||
TerminalLogger.debugf { "self mac: ${macToString(node.mac)}"}
|
||||
|
||||
@ -199,24 +200,34 @@ suspend fun run_sdlan(scope: CoroutineScope, iface: Iface, argument: Arguments,
|
||||
*/
|
||||
|
||||
scope.launch {
|
||||
while(true) {
|
||||
val data = node.iface?.recv()
|
||||
Log.d("SDLAN", "async receive data from iface: ${data?.size} bytes")
|
||||
if (data == null) {
|
||||
//delay(1000)
|
||||
println("got data is null")
|
||||
continue
|
||||
try {
|
||||
while(true) {
|
||||
if (node.iface == null) {
|
||||
delay(1000)
|
||||
continue
|
||||
}
|
||||
val data = node.iface?.recv()
|
||||
Log.d("SDLAN", "async receive data from iface: ${data?.size} bytes")
|
||||
if (data == null) {
|
||||
//delay(1000)
|
||||
delay(1000)
|
||||
// println("got data is null")
|
||||
continue
|
||||
}
|
||||
if (data.isEmpty()) {
|
||||
delay(1000)
|
||||
// println("got data size 0")
|
||||
// delay(1000)
|
||||
continue
|
||||
}
|
||||
Log.d("SDLAN", "handle data form device starts")
|
||||
node.iface?.handleDataFromDevice(node, data)
|
||||
Log.d("SDLAN", "handle data form device stops")
|
||||
}
|
||||
if (data.isEmpty()) {
|
||||
println("got data size 0")
|
||||
// delay(1000)
|
||||
continue
|
||||
}
|
||||
Log.d("SDLAN", "handle data form device starts")
|
||||
node.iface?.handleDataFromDevice(node, data)
|
||||
Log.d("SDLAN", "handle data form device stops")
|
||||
} catch (e: Exception) {
|
||||
println("iface read is cancelled")
|
||||
node.iface?.close()
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
CoroutineScope((Dispatchers.IO)).async {
|
||||
@ -242,20 +253,24 @@ suspend fun run_sdlan(scope: CoroutineScope, iface: Iface, argument: Arguments,
|
||||
|
||||
// CoroutineScope(Dispatchers.IO).async {
|
||||
scope.launch {
|
||||
initTCPConn(
|
||||
scope,
|
||||
tcp[0], tcp[1].toInt(),
|
||||
start_stop_channel,
|
||||
AtomicLong(now),
|
||||
AtomicBoolean(false),
|
||||
toSocket as ReceiveChannel<ByteArray>,
|
||||
onConnected,
|
||||
::onMessage,
|
||||
suspend {
|
||||
node.aes.setSecret(null)
|
||||
},
|
||||
null,
|
||||
)
|
||||
try {
|
||||
initTCPConn(
|
||||
scope,
|
||||
tcp[0], tcp[1].toInt(),
|
||||
start_stop_channel,
|
||||
AtomicLong(now),
|
||||
AtomicBoolean(false),
|
||||
toSocket as ReceiveChannel<ByteArray>,
|
||||
onConnected,
|
||||
::onMessage,
|
||||
suspend {
|
||||
node.aes.setSecret(null)
|
||||
},
|
||||
null,
|
||||
)
|
||||
} finally {
|
||||
println("initTCPConn is cancelled")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -354,6 +369,7 @@ suspend fun handleAPacket(scope: CoroutineScope, node: Node, from: SocketAddress
|
||||
return
|
||||
}
|
||||
PacketType.Register -> {
|
||||
TerminalLogger.debugf { "got REGISTER" }
|
||||
if (from is InetSocketAddress) {
|
||||
val sock = SDLanSock(IPFamily.IPV4, from.port, from.address.address)
|
||||
handlePacketRegister(node, data, sock)
|
||||
@ -419,17 +435,20 @@ suspend fun initTCPConn(
|
||||
onDisconnected: suspend ()->Unit,
|
||||
connectingChan: SendChannel<ConnectingState>?
|
||||
) {
|
||||
var started: Boolean = false
|
||||
val started = AtomicBoolean(false)
|
||||
// var started: Boolean = false
|
||||
var startPktID: Int? = null
|
||||
|
||||
while(true) {
|
||||
connectingChan?.send(ConnectingState.NotConnected)
|
||||
|
||||
if (!started) {
|
||||
if (!started.get()) {
|
||||
while(true) {
|
||||
println("waiting for start_stop")
|
||||
val startStopInfo = start_stop.receive()
|
||||
if (startStopInfo.flag == StartStopFlag.IsStart) {
|
||||
started = true
|
||||
started.set(true)
|
||||
// started = true
|
||||
startPktID = startStopInfo.packetID
|
||||
break
|
||||
}
|
||||
@ -518,11 +537,11 @@ suspend fun initTCPConn(
|
||||
try {
|
||||
val v = start_stop.receive()
|
||||
if (v.flag == StartStopFlag.IsStop) {
|
||||
started = false
|
||||
started.set(false)
|
||||
break
|
||||
}
|
||||
} catch(e: Exception) {
|
||||
started = false
|
||||
started.set(false)
|
||||
break
|
||||
}
|
||||
|
||||
@ -549,10 +568,15 @@ suspend fun initTCPConn(
|
||||
}
|
||||
}
|
||||
|
||||
println("m1")
|
||||
job_read_packet.cancelAndJoin()
|
||||
println("m2")
|
||||
job_write_to_packet.cancelAndJoin()
|
||||
println("m3")
|
||||
job_check_pong.cancelAndJoin()
|
||||
println("m4")
|
||||
job_check_stop.cancelAndJoin()
|
||||
println("m5")
|
||||
|
||||
delay(1000)
|
||||
}
|
||||
|
||||
@ -43,21 +43,13 @@ class AES private constructor () {
|
||||
if (!isAuthorized()) {
|
||||
return null
|
||||
}
|
||||
println(11.0)
|
||||
val cipher = Cipher.getInstance(AESConfig.CIPHER_ALGORITHM)
|
||||
println(11.1)
|
||||
val keyspec = SecretKeySpec(_secret, AESConfig.KEY_SPEC)
|
||||
println(11.2)
|
||||
println(11.3)
|
||||
try {
|
||||
cipher.init(Cipher.ENCRYPT_MODE, keyspec, IvParameterSpec(_iv))
|
||||
println(10.0)
|
||||
val output = ByteBuffer.allocate(cipher.getOutputSize(content.remaining()))
|
||||
println(10.1)
|
||||
cipher.doFinal(content, output)
|
||||
println(10.2)
|
||||
output.flip()
|
||||
println(10.3)
|
||||
return output
|
||||
} catch (e: Exception) {
|
||||
println("failed to encrypt: ${e.toString()}")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user