punchnet-macos/Tun/Punchnet/Actors/SDLLayerPacketForwarder.swift
2026-04-16 10:42:44 +08:00

67 lines
2.2 KiB
Swift

//
// 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) async 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)
}
let preferredSessionType = Session.AddressType(packetType: type)
if let session = await self.sessionManager.getSession(toAddress: dstMac, preferredType: preferredSessionType) {
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()
}
}