fix outbound路径

This commit is contained in:
anlicheng 2026-05-20 22:13:22 +08:00
parent 76b5d3212f
commit ced138c3a5
3 changed files with 56 additions and 84 deletions

View File

@ -12,6 +12,12 @@ import NIOCore
actor PacketOutboundActor { actor PacketOutboundActor {
private typealias PacketReadResult = (packets: [Data], protocols: [NSNumber])? 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 provider: NEPacketTunnelProvider
private let sessionManager: SessionManager private let sessionManager: SessionManager
private let arpResolver: ArpResolver private let arpResolver: ArpResolver
@ -112,7 +118,7 @@ actor PacketOutboundActor {
} }
func handleTunPacket(_ packet: IPPacket) async { 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) let decision = router.route(packet: packet)
if decision.shouldTrackFlow, let flowSession = packet.flowSession() { if decision.shouldTrackFlow, let flowSession = packet.flowSession() {
@ -146,8 +152,7 @@ actor PacketOutboundActor {
} }
func routeLayerPacket(dstMac: Data, type: LayerPacket.PacketType, data: Data) async { func routeLayerPacket(dstMac: Data, type: LayerPacket.PacketType, data: Data) async {
let forwarder = self.makeLayerPacketForwarder() guard let plan = try? self.makeDeliveryPlan(dstMac: dstMac, type: type, data: data) else {
guard let plan = try? forwarder.makeDeliveryPlan(dstMac: dstMac, type: type, data: data) else {
return 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 { switch decision {
case .loopback(let ipPacketData): case .loopback(let ipPacketData):
let nePacket = NEPacket(data: ipPacketData, protocolFamily: 2) 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 { switch kind {
case .sameNetwork: case .sameNetwork:
SDLLogger.log("[PacketOutboundActor] dstIp: \(SDLUtil.int32ToIp(ip)) same network", for: .trace) 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 { private func sendSuperPacket(type: SDLPacketType, data: Data) async {
await self.sendPacket(type: type, data: data, remoteAddress: self.stunSocketAddress) await self.sendPacket(type: type, data: data, remoteAddress: self.stunSocketAddress)
} }

View File

@ -1,5 +1,5 @@
// //
// SDLTunPacketRouter.swift // PacketOutboundRouter.swift
// Tun // Tun
// //
// Created by on 2026/4/14. // Created by on 2026/4/14.
@ -7,7 +7,7 @@
import Foundation import Foundation
struct SDLTunPacketRouter { struct PacketOutboundRouter {
enum DropReason: String { enum DropReason: String {
case invalidDNSRequest case invalidDNSRequest
case noRoute case noRoute
@ -95,7 +95,7 @@ struct SDLTunPacketRouter {
} }
} }
extension SDLTunPacketRouter.RouteDecision { extension PacketOutboundRouter.RouteDecision {
var shouldTrackFlow: Bool { var shouldTrackFlow: Bool {
switch self { switch self {

View File

@ -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()
}
}