diff --git a/Tun/Punchnet/Outbound/PacketOutboundActor.swift b/Tun/Punchnet/Outbound/PacketOutboundActor.swift index 506054a..9378a77 100644 --- a/Tun/Punchnet/Outbound/PacketOutboundActor.swift +++ b/Tun/Punchnet/Outbound/PacketOutboundActor.swift @@ -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) @@ -127,6 +127,66 @@ actor PacketOutboundActor { await self.handleTunRouteDecision(decision) } + + 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) + } + } + } + + func routeLayerPacket(dstMac: Data, type: LayerPacket.PacketType, data: Data) async { + guard let plan = try? self.makeDeliveryPlan(dstMac: dstMac, type: type, data: data) else { + return + } + + switch plan { + case .superNode(let payload): + await self.sendSuperPacket(type: .data, data: payload) + case .peer(let payload, let session): + SDLLogger.log("[PacketOutboundActor] step 5 send packet by session: \(session)", for: .trace) + await self.sendPeerPacket(type: .data, data: payload, remoteAddress: session.natAddress) + self.flowTracer.inc(num: payload.count, type: .p2p) + case .superNodeAndPunch(let payload, let request): + await self.sendSuperPacket(type: .data, data: payload) + SDLLogger.log("[PacketOutboundActor] step 5 send packet by super: \(self.stunSocketAddress)", for: .trace) + self.flowTracer.inc(num: payload.count, type: .forward) + + if let queryData = await self.puncherActor.makeQueryInfoRequest(request: request) { + await self.superServiceProxy.send(type: .queryInfo, data: queryData) + } + } + } private func finishPacketReader(generation: UInt64) { guard generation == self.packetReaderGeneration else { @@ -150,30 +210,7 @@ actor PacketOutboundActor { readContinuation.resume(returning: nil) } } - - func routeLayerPacket(dstMac: Data, type: LayerPacket.PacketType, data: Data) async { - guard let plan = try? self.makeDeliveryPlan(dstMac: dstMac, type: type, data: data) else { - return - } - - switch plan { - case .superNode(let payload): - await self.sendSuperPacket(type: .data, data: payload) - case .peer(let payload, let session): - SDLLogger.log("[PacketOutboundActor] step 5 send packet by session: \(session)", for: .trace) - await self.sendPeerPacket(type: .data, data: payload, remoteAddress: session.natAddress) - self.flowTracer.inc(num: payload.count, type: .p2p) - case .superNodeAndPunch(let payload, let request): - await self.sendSuperPacket(type: .data, data: payload) - SDLLogger.log("[PacketOutboundActor] step 5 send packet by super: \(self.stunSocketAddress)", for: .trace) - self.flowTracer.inc(num: payload.count, type: .forward) - - if let queryData = await self.puncherActor.makeQueryInfoRequest(request: request) { - await self.superServiceProxy.send(type: .queryInfo, data: queryData) - } - } - } - + 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) }