123 lines
3.4 KiB
Swift
123 lines
3.4 KiB
Swift
//
|
|
// Session.swift
|
|
// sdlan
|
|
// Session是增加了有效时间的
|
|
// Created by 安礼成 on 2025/7/14.
|
|
//
|
|
import Foundation
|
|
import NIOCore
|
|
import Darwin
|
|
|
|
struct Session: @unchecked Sendable {
|
|
enum AddressType: String, Hashable {
|
|
case v4
|
|
case v6
|
|
|
|
init?(socketAddress: SocketAddress) {
|
|
switch socketAddress {
|
|
case .v4:
|
|
self = .v4
|
|
case .v6:
|
|
self = .v6
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
init?(packetType: LayerPacket.PacketType) {
|
|
switch packetType {
|
|
case .arp, .ipv4:
|
|
self = .v4
|
|
case .ipv6:
|
|
self = .v6
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
|
|
// 在内部的通讯的ip地址, 整数格式
|
|
let dstMac: Data
|
|
// 对端的主机在nat上映射的端口信息
|
|
let natAddress: SocketAddress
|
|
// 当前会话对应的外层地址族
|
|
let addressType: AddressType
|
|
|
|
// 最后使用时间
|
|
var lastTimestamp: Int32
|
|
|
|
init?(dstMac: Data, natAddress: SocketAddress) {
|
|
guard let addressType = AddressType(socketAddress: natAddress) else {
|
|
return nil
|
|
}
|
|
|
|
self.dstMac = dstMac
|
|
self.natAddress = natAddress
|
|
self.addressType = addressType
|
|
self.lastTimestamp = Int32(Date().timeIntervalSince1970)
|
|
}
|
|
|
|
mutating func updateLastTimestamp(_ lastTimestamp: Int32) {
|
|
self.lastTimestamp = lastTimestamp
|
|
}
|
|
}
|
|
|
|
actor SessionManager {
|
|
private var sessions: [Data: [Session.AddressType: Session]] = [:]
|
|
|
|
// session的有效时间
|
|
private let ttl: Int32 = 10
|
|
|
|
func getSession(toAddress: Data, preferredType: Session.AddressType? = nil) -> Session? {
|
|
let timestamp = Int32(Date().timeIntervalSince1970)
|
|
|
|
guard var sessions = self.sessions[toAddress] else {
|
|
return nil
|
|
}
|
|
|
|
sessions = sessions.filter { $0.value.lastTimestamp + ttl >= timestamp }
|
|
guard !sessions.isEmpty else {
|
|
self.sessions.removeValue(forKey: toAddress)
|
|
return nil
|
|
}
|
|
|
|
guard var session = self.selectSession(in: sessions, preferredType: preferredType) else {
|
|
self.sessions[toAddress] = sessions
|
|
return nil
|
|
}
|
|
|
|
session.updateLastTimestamp(timestamp)
|
|
sessions[session.addressType] = session
|
|
self.sessions[toAddress] = sessions
|
|
|
|
return session
|
|
}
|
|
|
|
func addSession(session: Session) {
|
|
let timestamp = Int32(Date().timeIntervalSince1970)
|
|
|
|
var sessions = self.sessions[session.dstMac, default: [:]]
|
|
sessions = sessions.filter {
|
|
$0.value.lastTimestamp + ttl >= timestamp && $0.key != session.addressType
|
|
}
|
|
sessions[session.addressType] = session
|
|
|
|
self.sessions[session.dstMac] = sessions
|
|
}
|
|
|
|
func removeSession(dstMac: Data) {
|
|
self.sessions.removeValue(forKey: dstMac)
|
|
}
|
|
|
|
private func selectSession(in sessions: [Session.AddressType: Session], preferredType: Session.AddressType?) -> Session? {
|
|
if let preferredType {
|
|
if let preferred = sessions[preferredType] {
|
|
return preferred
|
|
}
|
|
}
|
|
|
|
return sessions.values.max(by: { $0.lastTimestamp < $1.lastTimestamp })
|
|
}
|
|
|
|
}
|