fix session

This commit is contained in:
anlicheng 2026-05-21 14:35:43 +08:00
parent 8383743f2c
commit 6e0e40c398
3 changed files with 79 additions and 67 deletions

View File

@ -0,0 +1,36 @@
//
// Session.swift
// sdlan
// Session
// Created by on 2025/7/14.
//
import Foundation
import NIOCore
struct Session {
enum AddressType: String, Hashable {
case v4
case v6
}
// ip,
let dstMac: Data
// nat
let natAddress: SocketAddress
//
let addressType: AddressType
// 使
var lastTimestamp: Int32
init?(dstMac: Data, natAddress: SocketAddress, addressType: AddressType) {
self.dstMac = dstMac
self.natAddress = natAddress
self.addressType = addressType
self.lastTimestamp = Int32(Date().timeIntervalSince1970)
}
mutating func updateLastTimestamp(_ lastTimestamp: Int32) {
self.lastTimestamp = lastTimestamp
}
}

View File

@ -0,0 +1,27 @@
//
// SessionSnapshot.swift
// Tun
//
// Created by Codex on 2026/5/21.
//
import Foundation
final class SessionSnapshot: Snapshot {
private let sessions: [Data: [Session.AddressType: Session]]
init(sessions: [Data: [Session.AddressType: Session]]) {
self.sessions = sessions
}
func getSession(toAddress: Data) -> Session? {
guard let peerSessions = self.sessions[toAddress] else {
return nil
}
return peerSessions.values.max(by: { $0.lastTimestamp < $1.lastTimestamp })
}
static func empty() -> SessionSnapshot {
return SessionSnapshot(sessions: [:])
}
}

View File

@ -1,64 +1,14 @@
// //
// Session.swift // SessionTable.swift
// sdlan // Tun
// Session //
// Created by on 2025/7/14. // Created by Codex on 2026/5/21.
// //
import Foundation import Foundation
import NIOCore
import Darwin
struct Session {
enum AddressType: String, Hashable {
case v4
case v6
}
// ip,
let dstMac: Data
// nat
let natAddress: SocketAddress
//
let addressType: AddressType
// 使
var lastTimestamp: Int32
init?(dstMac: Data, natAddress: SocketAddress, addressType: AddressType) {
self.dstMac = dstMac
self.natAddress = natAddress
self.addressType = addressType
self.lastTimestamp = Int32(Date().timeIntervalSince1970)
}
mutating func updateLastTimestamp(_ lastTimestamp: Int32) {
self.lastTimestamp = lastTimestamp
}
}
final class SessionSnapshot: Snapshot {
private let sessions: [Data: [Session.AddressType: Session]]
init(sessions: [Data: [Session.AddressType: Session]]) {
self.sessions = sessions
}
func getSession(toAddress: Data) -> Session? {
guard let peerSessions = self.sessions[toAddress] else {
return nil
}
return peerSessions.values.max(by: { $0.lastTimestamp < $1.lastTimestamp })
}
static func empty() -> SessionSnapshot {
return SessionSnapshot(sessions: [:])
}
}
actor SessionManager { actor SessionManager {
private var sessions: [Data: [Session.AddressType: Session]] = [:] private var sessions: [Data: [Session.AddressType: Session]] = [:]
// session // session
private let ttl: Int32 private let ttl: Int32
nonisolated private let snapshotPublisher: SnapshotPublisher<SessionSnapshot> nonisolated private let snapshotPublisher: SnapshotPublisher<SessionSnapshot>
@ -68,54 +18,54 @@ actor SessionManager {
self.ttl = ttl self.ttl = ttl
self.snapshotPublisher = SnapshotPublisher(initial: SessionSnapshot.empty()) self.snapshotPublisher = SnapshotPublisher(initial: SessionSnapshot.empty())
} }
func getSession(toAddress: Data) -> Session? { func getSession(toAddress: Data) -> Session? {
let timestamp = Int32(Date().timeIntervalSince1970) let timestamp = Int32(Date().timeIntervalSince1970)
guard var peerSessions = self.sessions[toAddress] else { guard var peerSessions = self.sessions[toAddress] else {
return nil return nil
} }
peerSessions = peerSessions.filter { $0.value.lastTimestamp + ttl >= timestamp } peerSessions = peerSessions.filter { $0.value.lastTimestamp + ttl >= timestamp }
guard !peerSessions.isEmpty else { guard !peerSessions.isEmpty else {
self.sessions.removeValue(forKey: toAddress) self.sessions.removeValue(forKey: toAddress)
self.publishSnapshot() self.publishSnapshot()
return nil return nil
} }
guard var session = self.selectSession(in: peerSessions) else { guard var session = self.selectSession(in: peerSessions) else {
self.sessions[toAddress] = peerSessions self.sessions[toAddress] = peerSessions
self.publishSnapshot() self.publishSnapshot()
return nil return nil
} }
session.updateLastTimestamp(timestamp) session.updateLastTimestamp(timestamp)
peerSessions[session.addressType] = session peerSessions[session.addressType] = session
self.sessions[toAddress] = peerSessions self.sessions[toAddress] = peerSessions
self.publishSnapshot() self.publishSnapshot()
return session return session
} }
func addSession(session: Session) { func addSession(session: Session) {
let timestamp = Int32(Date().timeIntervalSince1970) let timestamp = Int32(Date().timeIntervalSince1970)
var sessions = self.sessions[session.dstMac, default: [:]] var sessions = self.sessions[session.dstMac, default: [:]]
sessions = sessions.filter { sessions = sessions.filter {
$0.value.lastTimestamp + ttl >= timestamp && $0.key != session.addressType $0.value.lastTimestamp + ttl >= timestamp && $0.key != session.addressType
} }
sessions[session.addressType] = session sessions[session.addressType] = session
self.sessions[session.dstMac] = sessions self.sessions[session.dstMac] = sessions
self.publishSnapshot() self.publishSnapshot()
} }
func removeSession(dstMac: Data) { func removeSession(dstMac: Data) {
self.sessions.removeValue(forKey: dstMac) self.sessions.removeValue(forKey: dstMac)
self.publishSnapshot() self.publishSnapshot()
} }
func clear() { func clear() {
self.sessions.removeAll() self.sessions.removeAll()
self.publishSnapshot() self.publishSnapshot()
@ -141,5 +91,4 @@ actor SessionManager {
} }
return SessionSnapshot(sessions: sessions) return SessionSnapshot(sessions: sessions)
} }
} }