From 867fb5ca72cd5897d20e7ec54cf6cad746b107ac Mon Sep 17 00:00:00 2001 From: asxalex Date: Tue, 15 Jul 2025 16:36:50 +0800 Subject: [PATCH] =?UTF-8?q?changed=20scope.cancel,=20=E5=BD=93=E5=8D=8F?= =?UTF-8?q?=E7=A8=8B=E4=B8=8A=E4=B8=8B=E6=96=87=E8=A2=AB=E5=8F=96=E6=B6=88?= =?UTF-8?q?=EF=BC=8C=E4=BC=9A=E5=B0=86=E8=B5=84=E6=BA=90=E5=81=9A=E5=AF=B9?= =?UTF-8?q?=E5=BA=94=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/jihe/punchnet/PunchnetService.kt | 32 ++++-- .../com/jihe/punchnet/sdlan/network/edge.kt | 5 + .../com/jihe/punchnet/sdlan/network/iface.kt | 4 + .../com/jihe/punchnet/sdlan/network/libs.kt | 108 +++++++++++------- .../java/com/jihe/punchnet/sdlan/utils/aes.kt | 8 -- 5 files changed, 96 insertions(+), 61 deletions(-) diff --git a/app/src/main/java/com/jihe/punchnet/PunchnetService.kt b/app/src/main/java/com/jihe/punchnet/PunchnetService.kt index 34b0224..6d0db66 100644 --- a/app/src/main/java/com/jihe/punchnet/PunchnetService.kt +++ b/app/src/main/java/com/jihe/punchnet/PunchnetService.kt @@ -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(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() } } \ No newline at end of file diff --git a/app/src/main/java/com/jihe/punchnet/sdlan/network/edge.kt b/app/src/main/java/com/jihe/punchnet/sdlan/network/edge.kt index 0a6fe3a..ad3490d 100644 --- a/app/src/main/java/com/jihe/punchnet/sdlan/network/edge.kt +++ b/app/src/main/java/com/jihe/punchnet/sdlan/network/edge.kt @@ -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"} } } } diff --git a/app/src/main/java/com/jihe/punchnet/sdlan/network/iface.kt b/app/src/main/java/com/jihe/punchnet/sdlan/network/iface.kt index c9ed408..d094255 100644 --- a/app/src/main/java/com/jihe/punchnet/sdlan/network/iface.kt +++ b/app/src/main/java/com/jihe/punchnet/sdlan/network/iface.kt @@ -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() diff --git a/app/src/main/java/com/jihe/punchnet/sdlan/network/libs.kt b/app/src/main/java/com/jihe/punchnet/sdlan/network/libs.kt index a3350ab..3c104bc 100644 --- a/app/src/main/java/com/jihe/punchnet/sdlan/network/libs.kt +++ b/app/src/main/java/com/jihe/punchnet/sdlan/network/libs.kt @@ -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, 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(100) - val start_stop_channel = Channel(100) + // val start_stop_channel = Channel(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, - 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, + 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? ) { - 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) } diff --git a/app/src/main/java/com/jihe/punchnet/sdlan/utils/aes.kt b/app/src/main/java/com/jihe/punchnet/sdlan/utils/aes.kt index 13ae7e9..54577b2 100644 --- a/app/src/main/java/com/jihe/punchnet/sdlan/utils/aes.kt +++ b/app/src/main/java/com/jihe/punchnet/sdlan/utils/aes.kt @@ -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()}")