diff --git a/Tun/Punchnet/Actors/SDLContextActor.swift b/Tun/Punchnet/Actors/SDLContextActor.swift index a65f5c5..d1a6ab1 100644 --- a/Tun/Punchnet/Actors/SDLContextActor.swift +++ b/Tun/Punchnet/Actors/SDLContextActor.swift @@ -991,47 +991,42 @@ extension SDLContextActor { } } + private func makeLayerPacketForwarder() -> SDLLayerPacketForwarder { + return .init( + networkAddress: self.config.networkAddress, + identityID: self.config.identityId, + dataCipher: self.dataCipher, + sessionManager: self.sessionManager + ) + } + private func routeLayerPacket(dstMac: Data, type: LayerPacket.PacketType, data: Data) async { - let networkAddr = self.config.networkAddress // 将数据封装层2层的数据包 - let layerPacket = LayerPacket(dstMac: dstMac, srcMac: networkAddr.mac, type: type, data: data) - guard let dataCipher = self.dataCipher, - let encodedPacket = try? dataCipher.encrypt(plainText: layerPacket.marshal()) else { + // 构造数据包 + let forwarder = self.makeLayerPacketForwarder() + guard let plan = try? forwarder.makeDeliveryPlan(dstMac: dstMac, type: type, data: data) else { return } - // 构造数据包 - var dataPacket = SDLData() - dataPacket.networkID = networkAddr.networkId - dataPacket.srcMac = networkAddr.mac - dataPacket.dstMac = dstMac - dataPacket.ttl = 255 - dataPacket.identityID = self.config.identityId - dataPacket.data = encodedPacket - - let data = try! dataPacket.serializedData() // 广播地址不要去尝试打洞 - if ARPPacket.isBroadcastMac(dstMac) { + switch plan { + case .superNode(let payload): // 通过super_node进行转发 - self.sendSuperPacket(type: .data, data: data) - } - else { + self.sendSuperPacket(type: .data, data: payload) + case .peer(let payload, let session): // 通过session发送到对端 - if let session = self.sessionManager.getSession(toAddress: dstMac) { - SDLLogger.log("[SDLContext] step 5 send packet by session: \(session)", for: .trace) - self.sendPeerPacket(type: .data, data: data, remoteAddress: session.natAddress) - self.flowTracer.inc(num: data.count, type: .p2p) - } - else { - // 通过super_node进行转发 - self.sendSuperPacket(type: .data, data: data) - SDLLogger.log("[SDLContext] step 5 send packet by super: \(self.config.stunSocketAddress)", for: .trace) - // 流量统计 - self.flowTracer.inc(num: data.count, type: .forward) - - // 尝试打洞 - await self.puncherActor.submitRegisterRequest(quicClient: self.quicClient, request: .init(srcMac: networkAddr.mac, dstMac: dstMac, networkId: networkAddr.networkId)) - } + SDLLogger.log("[SDLContext] step 5 send packet by session: \(session)", for: .trace) + self.sendPeerPacket(type: .data, data: payload, remoteAddress: session.natAddress) + self.flowTracer.inc(num: payload.count, type: .p2p) + case .superNodeAndPunch(let payload, let request): + // 通过super_node进行转发 + self.sendSuperPacket(type: .data, data: payload) + SDLLogger.log("[SDLContext] step 5 send packet by super: \(self.config.stunSocketAddress)", for: .trace) + // 流量统计 + self.flowTracer.inc(num: payload.count, type: .forward) + + // 尝试打洞 + await self.puncherActor.submitRegisterRequest(quicClient: self.quicClient, request: request) } } diff --git a/Tun/Punchnet/Actors/SDLLayerPacketForwarder.swift b/Tun/Punchnet/Actors/SDLLayerPacketForwarder.swift new file mode 100644 index 0000000..1876cd5 --- /dev/null +++ b/Tun/Punchnet/Actors/SDLLayerPacketForwarder.swift @@ -0,0 +1,65 @@ +// +// SDLLayerPacketForwarder.swift +// Tun +// +// Created by 安礼成 on 2026/4/14. +// + +import Foundation + +struct SDLLayerPacketForwarder { + enum DeliveryPlan { + case superNode(payload: Data) + case peer(payload: Data, session: Session) + case superNodeAndPunch(payload: Data, request: SDLPuncherActor.RegisterRequest) + } + + let networkAddress: SDLConfiguration.NetworkAddress + let identityID: UInt32 + let dataCipher: CCDataCipher? + let sessionManager: SessionManager + + func makeDeliveryPlan(dstMac: Data, type: LayerPacket.PacketType, data: Data) throws -> DeliveryPlan? { + guard let payload = try self.makePayload(dstMac: dstMac, type: type, data: data) else { + return nil + } + + if ARPPacket.isBroadcastMac(dstMac) { + return .superNode(payload: payload) + } + + if let session = self.sessionManager.getSession(toAddress: dstMac) { + return .peer(payload: payload, session: session) + } + + return .superNodeAndPunch( + payload: payload, + request: .init( + srcMac: self.networkAddress.mac, + dstMac: dstMac, + networkId: self.networkAddress.networkId + ) + ) + } + + private func makePayload(dstMac: Data, type: LayerPacket.PacketType, data: Data) throws -> Data? { + // 将数据封装层2层的数据包 + let layerPacket = LayerPacket(dstMac: dstMac, srcMac: self.networkAddress.mac, type: type, data: data) + guard let dataCipher = self.dataCipher else { + return nil + } + + let encodedPacket = try dataCipher.encrypt(plainText: layerPacket.marshal()) + + // 构造数据包 + var dataPacket = SDLData() + dataPacket.networkID = self.networkAddress.networkId + dataPacket.srcMac = self.networkAddress.mac + dataPacket.dstMac = dstMac + dataPacket.ttl = 255 + dataPacket.identityID = self.identityID + dataPacket.data = encodedPacket + + return try dataPacket.serializedData() + } +}