diff --git a/Tun/Punchnet/Outbound/PacketOutboundActor.swift b/Tun/Punchnet/Outbound/PacketOutboundActor.swift index b5d7f86..12dfbf2 100644 --- a/Tun/Punchnet/Outbound/PacketOutboundActor.swift +++ b/Tun/Punchnet/Outbound/PacketOutboundActor.swift @@ -12,6 +12,12 @@ import NIOCore actor PacketOutboundActor { private typealias PacketReadResult = (packets: [Data], protocols: [NSNumber])? + private enum DeliveryPlan { + case superNode(payload: Data) + case peer(payload: Data, session: Session) + case superNodeAndPunch(payload: Data, request: SDLPuncherActor.RegisterRequest) + } + private let provider: NEPacketTunnelProvider private let sessionManager: SessionManager private let arpResolver: ArpResolver @@ -112,7 +118,7 @@ actor PacketOutboundActor { } func handleTunPacket(_ packet: IPPacket) async { - let router = SDLTunPacketRouter(networkAddress: self.networkAddress, exitNode: self.exitNode) + let router = PacketOutboundRouter(networkAddress: self.networkAddress, exitNode: self.exitNode) let decision = router.route(packet: packet) if decision.shouldTrackFlow, let flowSession = packet.flowSession() { @@ -146,8 +152,7 @@ actor PacketOutboundActor { } func routeLayerPacket(dstMac: Data, type: LayerPacket.PacketType, data: Data) async { - let forwarder = self.makeLayerPacketForwarder() - guard let plan = try? forwarder.makeDeliveryPlan(dstMac: dstMac, type: type, data: data) else { + guard let plan = try? self.makeDeliveryPlan(dstMac: dstMac, type: type, data: data) else { return } @@ -169,7 +174,50 @@ actor PacketOutboundActor { } } - private func handleTunRouteDecision(_ decision: SDLTunPacketRouter.RouteDecision) async { + private func makeDeliveryPlan(dstMac: Data, type: LayerPacket.PacketType, data: Data) throws -> DeliveryPlan? { + guard let payload = try self.makeDataPayload(dstMac: dstMac, type: type, data: data) else { + return nil + } + + if ARPPacket.isBroadcastMac(dstMac) { + return .superNode(payload: payload) + } + + if let session = self.sessionManager.snapshot().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 makeDataPayload(dstMac: Data, type: LayerPacket.PacketType, data: Data) throws -> Data? { + guard let dataCipher = self.dataCipher else { + return nil + } + + let layerPacket = LayerPacket(dstMac: dstMac, srcMac: self.networkAddress.mac, type: type, data: data) + 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.isP2P = true + dataPacket.data = encodedPacket + + return try dataPacket.serializedData() + } + + private func handleTunRouteDecision(_ decision: PacketOutboundRouter.RouteDecision) async { switch decision { case .loopback(let ipPacketData): let nePacket = NEPacket(data: ipPacketData, protocolFamily: 2) @@ -187,7 +235,7 @@ actor PacketOutboundActor { } } - private func forwardPacketToNextHop(ip: UInt32, type: LayerPacket.PacketType, data: Data, kind: SDLTunPacketRouter.ForwardKind) async { + private func forwardPacketToNextHop(ip: UInt32, type: LayerPacket.PacketType, data: Data, kind: PacketOutboundRouter.ForwardKind) async { switch kind { case .sameNetwork: SDLLogger.log("[PacketOutboundActor] dstIp: \(SDLUtil.int32ToIp(ip)) same network", for: .trace) @@ -206,15 +254,6 @@ actor PacketOutboundActor { } } - private func makeLayerPacketForwarder() -> SDLLayerPacketForwarder { - return .init( - networkAddress: self.networkAddress, - identityID: self.identityId, - dataCipher: self.dataCipher, - sessionSnapshot: self.sessionManager.snapshot() - ) - } - private func sendSuperPacket(type: SDLPacketType, data: Data) async { await self.sendPacket(type: type, data: data, remoteAddress: self.stunSocketAddress) } diff --git a/Tun/Punchnet/Outbound/SDLTunPacketRouter.swift b/Tun/Punchnet/Outbound/PacketOutboundRouter.swift similarity index 97% rename from Tun/Punchnet/Outbound/SDLTunPacketRouter.swift rename to Tun/Punchnet/Outbound/PacketOutboundRouter.swift index 9904241..5743575 100644 --- a/Tun/Punchnet/Outbound/SDLTunPacketRouter.swift +++ b/Tun/Punchnet/Outbound/PacketOutboundRouter.swift @@ -1,5 +1,5 @@ // -// SDLTunPacketRouter.swift +// PacketOutboundRouter.swift // Tun // // Created by 安礼成 on 2026/4/14. @@ -7,7 +7,7 @@ import Foundation -struct SDLTunPacketRouter { +struct PacketOutboundRouter { enum DropReason: String { case invalidDNSRequest case noRoute @@ -95,7 +95,7 @@ struct SDLTunPacketRouter { } } -extension SDLTunPacketRouter.RouteDecision { +extension PacketOutboundRouter.RouteDecision { var shouldTrackFlow: Bool { switch self { diff --git a/Tun/Punchnet/Outbound/SDLLayerPacketForwarder.swift b/Tun/Punchnet/Outbound/SDLLayerPacketForwarder.swift deleted file mode 100644 index e6267b8..0000000 --- a/Tun/Punchnet/Outbound/SDLLayerPacketForwarder.swift +++ /dev/null @@ -1,67 +0,0 @@ -// -// 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 sessionSnapshot: SessionSnapshot - - 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.sessionSnapshot.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.isP2P = true - dataPacket.data = encodedPacket - - return try dataPacket.serializedData() - } -}