fix outbound

This commit is contained in:
anlicheng 2026-05-20 22:38:08 +08:00
parent 604dad0584
commit 4c1e09cbbb

View File

@ -117,7 +117,7 @@ actor PacketOutboundActor {
packetReaderTask?.cancel()
}
func handleTunPacket(_ packet: IPPacket) {
func handleTunPacket(_ packet: IPPacket) async {
let router = PacketOutboundRouter(networkAddress: self.networkAddress, exitNode: self.exitNode)
let decision = router.route(packet: packet)
@ -128,26 +128,40 @@ actor PacketOutboundActor {
await self.handleTunRouteDecision(decision)
}
private func finishPacketReader(generation: UInt64) {
guard generation == self.packetReaderGeneration else {
return
private func handleTunRouteDecision(_ decision: PacketOutboundRouter.RouteDecision) async {
switch decision {
case .loopback(let ipPacketData):
let nePacket = NEPacket(data: ipPacketData, protocolFamily: 2)
self.provider.packetFlow.writePacketObjects([nePacket])
case .cloudDNS(let name, let ipPacketData):
SDLLogger.log("[PacketOutboundActor] get cloud dns request: \(name)")
await self.dnsService?.forward(ipPacketData: ipPacketData)
case .localDNS(let name, let payload, let tracker):
SDLLogger.log("[PacketOutboundActor] get local dns request: \(name)")
await self.dnsService?.queryLocal(tracker: tracker, dnsPayload: payload)
case .forwardToNextHop(let ip, let type, let data, let kind):
await self.forwardPacketToNextHop(ip: ip, type: type, data: data, kind: kind)
case .drop(let reason):
SDLLogger.log("[PacketOutboundActor] drop tun packet, reason: \(reason.rawValue)", for: .trace)
}
self.packetReaderTask = nil
}
private static func readPackets(from provider: NEPacketTunnelProvider) async -> PacketReadResult {
let readContinuation = OnceContinuation<PacketReadResult, Never>()
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)
case .exitNode, .dnsExitNode:
SDLLogger.log("[PacketOutboundActor] use exit_node: \(SDLUtil.int32ToIp(ip))", for: .trace)
}
return await withTaskCancellationHandler {
await withCheckedContinuation { continuation in
readContinuation.set(continuation)
provider.packetFlow.readPackets { packets, protocols in
readContinuation.resume(returning: (packets: packets, protocols: protocols))
}
if let dstMac = self.arpResolver.snapshot().lookup(ip) {
SDLLogger.log("[PacketOutboundActor] dstIp: \(SDLUtil.int32ToIp(ip)), dst_mac is: \(SDLUtil.formatMacAddress(mac: dstMac))", for: .trace)
await self.routeLayerPacket(dstMac: dstMac, type: type, data: data)
} else {
SDLLogger.log("[PacketOutboundActor] dstIp: \(SDLUtil.int32ToIp(ip)) arp query not found, broadcast", for: .trace)
if let arpRequest = try? await self.arpResolver.makeArpRequest(targetIp: ip) {
await self.superServiceProxy.send(type: .arpRequest, data: arpRequest)
}
} onCancel: {
readContinuation.resume(returning: nil)
}
}
@ -174,6 +188,29 @@ actor PacketOutboundActor {
}
}
private func finishPacketReader(generation: UInt64) {
guard generation == self.packetReaderGeneration else {
return
}
self.packetReaderTask = nil
}
private static func readPackets(from provider: NEPacketTunnelProvider) async -> PacketReadResult {
let readContinuation = OnceContinuation<PacketReadResult, Never>()
return await withTaskCancellationHandler {
await withCheckedContinuation { continuation in
readContinuation.set(continuation)
provider.packetFlow.readPackets { packets, protocols in
readContinuation.resume(returning: (packets: packets, protocols: protocols))
}
}
} onCancel: {
readContinuation.resume(returning: nil)
}
}
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
@ -217,43 +254,6 @@ actor PacketOutboundActor {
return try dataPacket.serializedData()
}
private func handleTunRouteDecision(_ decision: PacketOutboundRouter.RouteDecision) async {
switch decision {
case .loopback(let ipPacketData):
let nePacket = NEPacket(data: ipPacketData, protocolFamily: 2)
self.provider.packetFlow.writePacketObjects([nePacket])
case .cloudDNS(let name, let ipPacketData):
SDLLogger.log("[PacketOutboundActor] get cloud dns request: \(name)")
await self.dnsService?.forward(ipPacketData: ipPacketData)
case .localDNS(let name, let payload, let tracker):
SDLLogger.log("[PacketOutboundActor] get local dns request: \(name)")
await self.dnsService?.queryLocal(tracker: tracker, dnsPayload: payload)
case .forwardToNextHop(let ip, let type, let data, let kind):
await self.forwardPacketToNextHop(ip: ip, type: type, data: data, kind: kind)
case .drop(let reason):
SDLLogger.log("[PacketOutboundActor] drop tun packet, reason: \(reason.rawValue)", for: .trace)
}
}
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)
case .exitNode, .dnsExitNode:
SDLLogger.log("[PacketOutboundActor] use exit_node: \(SDLUtil.int32ToIp(ip))", for: .trace)
}
if let dstMac = self.arpResolver.snapshot().lookup(ip) {
SDLLogger.log("[PacketOutboundActor] dstIp: \(SDLUtil.int32ToIp(ip)), dst_mac is: \(SDLUtil.formatMacAddress(mac: dstMac))", for: .trace)
await self.routeLayerPacket(dstMac: dstMac, type: type, data: data)
} else {
SDLLogger.log("[PacketOutboundActor] dstIp: \(SDLUtil.int32ToIp(ip)) arp query not found, broadcast", for: .trace)
if let arpRequest = try? await self.arpResolver.makeArpRequest(targetIp: ip) {
await self.superServiceProxy.send(type: .arpRequest, data: arpRequest)
}
}
}
private func sendSuperPacket(type: SDLPacketType, data: Data) async {
await self.sendPacket(type: type, data: data, remoteAddress: self.stunSocketAddress)
}